Como entender o comando awk '{para (x = 1; $ x; ++ x) print $ x}'?

5

Eu conheço este comando

awk '{for(x=1;$x;++x)print $x}' 

imprimirá todas as colunas em uma linha.

isso não seria ++x alteração x para 2 e, portanto, imprimir $2 primeiro? Como eu entendi com base nisso: link

E o que o $x faz em for(x=1;$x;++x) ?

    
por Zen 08.08.2014 / 16:11

3 respostas

13

Não. O for(i=0;i<10;i++) é um constructo de programação clássico (veja Traditional for loops ) que está presente em vários idiomas. Pode ser dividido em:

start-expression; end-condition; end-of-iteration-expression

Em outras palavras, o que escrevi acima significa "inicializar i para 0 e, enquanto i é menor que 10, fazer alguma coisa e então incrementar i por 1. Sim, a sintaxe é confusa, mas isso é apenas A forma como é. O end-of-iteration-expression ( ++x neste caso) é executado uma vez no final de cada loop. É equivalente a escrever:

while(i<10){print i; ++i}

Quanto ao $x , acredito que apenas verifica se existe um campo desse número e se seu conteúdo não é avaliado como falso (conforme explicado em Mathias responder abaixo ). $N retornará verdadeiro se o número do campo N existir e não for um tipo de false . Por exemplo:

$ echo "a b c d" | awk '($4){print "yes"}'
yes
$ echo "a b c d" | awk '($14){print "yes"}' ## prints nothing, no $14
$ echo "a b c 0" | awk '($4){print "yes"}' ## prints nothing, $4 is 0

Como você pode ver acima, o primeiro comando imprime yes porque existe um $4 . Como não há $14 , o segundo não imprime nada. Então, para voltar ao seu exemplo original:

awk '{for(x=1;$x;x++)print $x}' 
          ___ __ ___
           |   |  |
           |   |  |-----> increment x by 1 at the end of each loop.
           |   |--------> run the loop as long as there is a field number x
           |------------> initialize x to 1
    
por 08.08.2014 / 16:19
6

Como o terdon forneceu uma resposta abrangente, só quero acrescentar que, se alguma coluna for avaliada como false, a instrução for encerrará o loop, como você pode ver neste exemplo:

$ echo 1 2 3 4 5 0 6|awk '{for(x=1;$x;++x)print $x}' 
1
2
3
4
5
    
por 08.08.2014 / 16:40
3
  1. ++x e x++ são funcionalmente equivalentes quando usados de maneira independente. Conforme discutido na pergunta sobre estouro de pilha que você mencionou,

    • Pode haver diferenças desempenho (ou seja, tempo).
    • Os resultados de something = ++x; e something = x++; são diferentes - mas seu exemplo não está fazendo isso.

    Então, no que diz respeito ao incremento de x , seu exemplo é equivalente a

    awk '{for(x=1;$x;x++) print $x}'
    
  2. O% autônomo$x é equivalente a $x != "" , então o loop irá iterar até encontrar um campo em branco. Este é um atalho preguiçoso para x <= NF , onde NF é o número de campos no registro atual (linha). Para os propósitos do seu exemplo, isso é inofensivo, AFAICT. Mas, se você especificar um separador de campo não padrão,

    awk -F, '{for(x=1;$x;++x) print $x}'
    

    isso tentará fazer o mesmo que o seu exemplo, mas dividindo as linhas em vírgulas. Se você digitar a b , a saída será a b . Se você digitar a,b , ele imprimirá a e b em linhas separadas. Mas se você inserir a,,b , ele produzirá a e depois parará, porque $2 é nulo.

por 08.08.2014 / 16:37

Tags