Por que o awk se comporta de maneira diferente para $1 se o valor for 0 (número zero)?

Por que o awk se comporta de maneira diferente para $1 se o valor for 0 (número zero)?

Quando awk recebe"0"como entrada, ele se comporta de maneira diferente em alguns casos. Código abaixo:

var=$1
echo ""; echo -n 'o/p of $1=$1 ==>'; echo $var | awk '$1=$1'
echo "";echo -n 'o/p of {$1=$1;print} ==>';echo $var | awk '{$1=$1;print}'
echo "";echo -n 'o/p of $1==$1 ==>';echo $var | awk '$1==$1'
echo "";echo -n 'o/p of {$1==$1;print} ==>';echo $var | awk '{$1==$1;print}'

A saída com"0" (número zero):

[root@host ~]# sh /tmp/te.sh 0

o/p of $1=$1 ==>
o/p of {$1=$1;print} ==>0

o/p of $1==$1 ==>0

o/p of {$1==$1;print} ==>0
[root@GORJALA ~]#

A saída com"1" (número um):

[root@host ~]# sh /tmp/te.sh 1

o/p of $1=$1 ==>1

o/p of {$1=$1;print} ==>1

o/p of $1==$1 ==>1

o/p of {$1==$1;print} ==>1
[root@host ~]#

Por que há uma diferença quando eu uso var=0; echo $var | awk '$1=$1'e var=1; echo $var | awk '$1=$1'? Todos os números estão funcionando bem, exceto 0.

Versões:

  • GNU bash, versão 4.2.46
  • GNU Awk 4.0.2
  • coreutils-8.22-24.el7.x86_64

Responder1

DeO Guia do Usuário GNU Awk:

Uma atribuição é uma expressão, portanto tem um valor – o mesmo valor atribuído. Assim, 'z = 1' é uma expressão com valor um.

Então

  • echo 0 | awk '$1=$1'o padrão é avaliado como 0 (FALSO)

  • echo 1 | awk '$1=$1'o padrão é avaliado como 1 (TRUE) e a ação padrão printé executada

Responder2

Não creio que seja uma questão de valor numérico: as conversões padrão cuidam disso (aqui, pelo menos).

O OP mostra quatro códigos awk diferentes, todas variações de: padrão {ação}

(a) $ 1 = $ 1

Isso reatribui $ 1 a si mesmo. Não é um teste booleano, é autônomo (efetivamente) e retorna o valor de $ 1. Se $1 for 0, o padrão éfalsoe o padrãoa ação de impressão é ignorada completamente. Se $1 for diferente de zero, oa entrada é impressa.

(b) { $1 = $1; imprimir; }

Isso reatribui $ 1 a si mesmo, também autônomo. Na ausência de um padrão, a ação é executada e a entrada ésempre impresso.

(c) $ 1 == $ 1

Essa é uma expressão booleana que ésempre verdade. 0 é 0 e 1 é 1 (e porco-da-terra é porco-da-terra). Na ausência de uma ação, a entrada ésempre impresso.

(d) { $1 == $1; imprimir; }

Não há padrão. A comparação é avaliada como um booleano verdadeiro que é descartado. A entrada ésempre impresso.

Responder3

As respostas existentes não conseguem explicar por que

echo 0 | awk '$0="0"'
echo 0 | awk '$0=substr($0,1)'
echo 0 | awk '$0=$0""'

todos serão impressos 0, mas

echo 0 | awk '$0'
echo 000 | awk '$0'

não imprimirá nada, embora em todos os casos a expressão padrão seja avaliada como 0.

Como é que 0é verdadeiro num caso e falso no outro?

Isso porque as “variáveis ​​de campo” (o resultado do $operador) são tratadas como umcaso especial, e (se possível) são automaticamente convertidos paracadeias numéricas, que, se numericamente igual a 0, será considerado falso quando usado em um contexto booleano:

Um valor de string deve ser considerado umsequência numéricase vier de um dos seguintes:

  1. Variáveis ​​de campo

  2. Entrada da getline()função

  3. FILENAME

  4. ARGVelementos da matriz

  5. ENVIRONelementos da matriz

  6. Elementos da matriz criados pela split()função

  7. Uma atribuição de variável de linha de comando

  8. Atribuição de variável de outra variável de string numérica

e [se parecer um número, leia toda a descriçãoaqui]

Por favor, leia também oRATIONALEpelas razões pelas quais o conceito de strings numéricas e esse invólucro especial eram necessários, especialmente a parte sobre uma comparação como echo 0 000 | awk '$1==$2'sendo verdadeira, mas não echo 0 | awk '$1=="000"'.


Como outra peculiaridade, observe que, pelo menos em algumas implementações, $0(o registro de entrada atual) perde sua propriedade mágica de "string numérica" ​​se uma atribuição a um subcampo fizer com que ele seja recalculado:

$ echo 0 | gawk '{$1=0} $0'
0

Isso não parece ser coberto pelo padrão, embora corresponda ao comportamento de nawk/bwk no qual o padrão awk se baseia (mas não ao de mawk).

Além disso, as implementações do awk podem reconhecer NAN, INFe INFINITYna entrada como os números de ponto flutuante correspondentes, embora o suporte para isso seja irregular e inconsistente. Você ainda pode ser mordido, por exemplo.

echo But his daughter named Nan | awk '$NF'

não imprimindo nada no awk do FreeBSD (bwk, original-awk).

Responder4

Porque $0 é oregistro inteiro(linha completa), $1, $2, sãoCampos(geralmente separados por espaços em branco) nele.

informação relacionada