Duplicando uma variável de string no awk

4

Eu gostaria de preceder cada linha com um número dizendo quantas barras a linha tem.

awk '{ l=$0; gsub("[^/]","",l); print length(l),l }' 

Isso não funciona, porque a l=$0 parece atribuir por referência. Como faço para dup a string?

Existe uma maneira melhor de fazer isso com as ferramentas padrão do UNIX? Eu essencialmente quero classificar uma lista de caminhos de arquivos por profundidade (contagem de barras).

    
por PSkocik 24.11.2015 / 20:25

3 respostas

5

Não, awk sempre faz a atribuição por valor, não por referência.

A RHS da atribuição de variáveis é uma expressão e uma expressão em awk sempre retorna um valor. Para duplicar uma variável, apenas atribuindo seu valor a uma nova variável, você pode operar em uma nova variável sem afetar a variável original.

Em:

$ echo 1 | awk '{l=$0; sub("1","2",l); print l, $0}'
2 1

apenas o valor de l foi modificado, $0 valor não foi alterado.

Com sua exigência na pergunta, basta fazer:

awk -F '/' '{print NF-1, $0}' <file

Você não precisa fazer nenhum trabalho de análise, deixe awk fazer tudo para você antes de entrar no corpo do script. Você só precisa extrair as informações.

    
por 25.11.2015 / 07:57
6

Pelo manual:

gsub(regexp, replacement [, target])

(se o alvo for omitido, o padrão é $0 ). gsub() retorna o número de substituições feitas, então, no seu caso, você quer substituir as barras por contagem:

awk '{l=$0; print gsub("/", ""), l}'

mas, como Etan Reisner percebe, a tarefa nem é necessária neste caso:

awk '{print gsub("/", "/"), $0}'
    
por 24.11.2015 / 21:00
4

Use split :

   split(s, a[, fs ])
             Split the string s into array elements a[1], a[2], ..., a[n],
             and return n.  All elements of the  array  shall  be  deleted
             before  the  split is performed. The separation shall be done
             with the ERE fs or with the field separator FS if fs  is  not
             given. [. . .]

Então, dado este arquivo de entrada:

$ cat file
no slashes
one / slash
two / and /
consecutive 3 ///
none
one /

Você poderia fazer:

$ awk '{ n=split($0,a,"/"); print n-1,$0}' file
0 no slashes
1 one / slash
2 two / and /
3 consecutive 3 ///
0 none
1 one /
    
por 24.11.2015 / 20:32

Tags