Não é possível entender os resultados da matriz de impressão para o awk?

0

Por um simples file que contém:

1        a
2        b
3        c
4        d
5        e
6        f
7        g
8        h
9        i
10       j

Eu uso esse comando:

awk 'lines[NR]=$0 { print $lines[2]}' 

Isso me fornece:

1        a
b
c
d
e
f
g
h
i
j

Como e por quê? Não deveria ser isso?

2 b

Além disso, quando eu atualizo com o seguinte

awk '{lines[NR]=$0} END { print lines[2]}' awk.write

2 b

com uso de $

j
    
por asad 06.01.2016 / 09:03

2 respostas

0

Em awk , você acessa o valor de uma variável referenciando-a:

$ awk 'BEGIN {var=1; print var}'
1

Existem variáveis especiais , que são chamadas de variáveis de campo, denotadas por um $ símbolo, seguido por um número ou uma expressão. Portanto, tanto $1 como $(0+1) fornecem o valor do primeiro campo.

No seu exemplo, você criou uma matriz associativa lines , cujas chaves são o número da linha, os valores são toda a linha. Para obter o valor da chave 2 , você deve usar lines[2] . Com $lines[2] , você se referiu ao enésimo campo, com enésimo é o valor retornado por lines[2] .

Quando você processa a primeira linha, lines[2] é não inicializado, então pode retornar 0 ou vazio ou o que quer que seja (o comportamento não é especificado por POSIX). Em qualquer caso, print e print $0 são os mesmos, por isso você obteve 1 a , que é $0 da primeira linha.

Da segunda linha, lines[2] é atribuído pelo conteúdo da segunda linha, que é 2 b , e no contexto numérico, 2 b return 2 , você obteve o valor do segundo campo $2 da segunda linha e assim por diante.

Agora, como a expressão após $ não é garantida para retornar um resultado numérico conforme especificado por POSIX:

Field variables shall be designated by a '$' followed by a number or numerical expression. The effect of the field number expression evaluating to anything other than a non-negative integer is unspecified; uninitialized variables or string values need not be converted to numeric values in this context

Portanto, pode haver implementações que serão quebradas. Pelo menos a versão do próprio Brian Kernighan :

$ echo 1 2 | bawk '{print $b}'
bawk: illegal field $(), name "b"
 input record number 1, file 
 source line number 1

Em qualquer caso, você pode forçar a expressão a ser avaliada no contexto numérico, adicionando 0 a ela:

$ echo 1 2 | awk '{print $(b+0)}'
1 2
    
por 06.01.2016 / 09:27
2

Você confundiu awk s varibales e fluxo de trabalho. O que você provavelmente quer é (imprima apenas a segunda linha):

awk '{lines[NR]=$0} END{print lines[2]}' file

Mas isso pode ser feito de maneira muito mais simples:

awk 'NR==2' file

Você comanda sua pergunta faz o seguinte:

awk 'lines[NR]=$0 { print $lines[2]}' 
  • lines[NR]=$0 isto é interpretado por awk como uma condição aqui. Observe que awk tem um fluxo de trabalho que possui um mecanismo como esse (que se aplica a todas as linhas): 'condition{instructions}' . lines[NR]=$0 preenche a matriz, mas, no entanto, é uma condição que é sempre verdadeira. É por isso que as instruções {...} block são executadas para cada linha.
  • print $lines[2] Isso não imprime o segundo item da matriz, lines[2] seria. $lines[2] se expande para uma variável cujo nome é o conteúdo do segundo item na matriz. Para a primeira linha, ele não é inicializado e, portanto, print é chamado sem argumento. Isso significa que imprime toda a linha. Mas quando definido (em todas as outras linhas), ele é expandido para print $2 . Isso significa, imprima o segundo campo da linha.
por 06.01.2016 / 09:25

Tags