Comportamento inconsistente no awk

1

Eu tenho um arquivo de texto chamado junk.txt :

hello
foo
0
-1
0
1
0
2
0
foo

Cindy
00000

Lou
2 000
0
Who
0000
0
wat?
0000 00000
0
0
0000 00000

filler

00

0
00
000
0000
0

0
bye

Quando executo o seguinte, recebo isso:

cat junk.txt | awk '{if (/foo/ ~ $1) print $1,"<-- found match"; else print $1}'
awk: cmd. line:1: warning: regular expression on left of '~' or '!~' operator
hello
foo
0 <-- found match
-1
0 <-- found match
1
0 <-- found match
2
0 <-- found match
foo
 <-- found match
Cindy
00000
 <-- found match
Lou
2
0 <-- found match
Who
0000
0
wat?
0000
0
0
0000
 <-- found match
filler
 <-- found match
00
 <-- found match
0 <-- found match
00 <-- found match
000 <-- found match
0000 <-- found match
0 <-- found match
 <-- found match
0 <-- found match
bye

Eu entendo o que está acontecendo quando a regex está à esquerda do ~ .

Eu entendo que uma 0 ou uma string vazia (null?) contará como uma correspondência.

O que eu não entendo é por que às vezes um 0 combina, e às vezes não. Parece que tem algo a ver com qualquer registro que tenha sido processado antes, mas eu achei que awk tratou cada registro de entrada independentemente para que eles não pudessem afetar um ao outro (pelo menos não sem algumas atribuições de variáveis ou outra manipulação). p>

EDIT: Caso seja importante, estou usando o GNU Awk 4.1.3

    
por Linoob 30.06.2016 / 00:01

2 respostas

4

De (g) man page do aws:

~ !~        Regular expression match, negated match.  NOTE: Do not use a constant regular  expression  (/foo/)
            on  the left-hand side of a ~ or !~.  Only use one on the right-hand side.  The expression /foo/ ~
            exp has the same meaning as (($0 ~ /foo/) ~ exp).  This is usually not what you want.

O que você espera que aconteça se você usá-lo de uma forma que explicitamente diga para você não fazer isso?

    
por 30.06.2016 / 00:08
3

Na verdade, essa é uma pergunta interessante. @tink apontou porque seu código não funciona como esperado, mas essa não foi a questão. A pergunta era "por que 0 às vezes corresponde".

Se (/foo/ ~ $1) realmente significa (($0 ~ /foo/) ~ $1) , então ($0 ~ /foo/) será avaliado como 1 se a linha contiver foo e 0 caso contrário. Assim, você está (principalmente) avaliando 0 ~ $1 . Se a linha de entrada estiver vazia, então $1 == "" e uma expressão regular vazia sempre corresponderão. Se a linha de entrada for exatamente 0 , o mesmo será $1 e 0 ~ 0 será true. Se a linha de entrada for 000 , por exemplo, o mesmo acontecerá com $1 e 0 ~ 000 não deverá ser verdadeiro. No entanto, é provável que o 000 seja convertido em 0 antes de a correspondência ser verificada.

Mas, infelizmente, essa explicação não cobre todos os casos.

Caso 1

0 <-- found match
a
0 <-- found match
0 <-- found match

Isso é exatamente como esperado.

Caso 2

0 <-- found match
00 00 <-- found match
0 <-- found match

Isso também é o esperado, desde que qualquer número de zeros seja interpretado como 0 . Mas agora, isso:

Caso 3

0 <-- found match
a
00 0
0

Isso não pode ser explicado de maneira tão simples. Depois de uma correspondência com falha, a conversão para zero não parece acontecer e as linhas seguintes devem corresponder a não.

Caso 4

0 <-- found match
a
00 00
a
0 <-- found match

Aconteça o que acontecer, outra correspondência com falha parece redefinir o comportamento de awk para normal e a correspondência funciona conforme o esperado novamente.

Para concluir, a explicação da página GNU awk man, que não faz parte da página de informações, por acaso, está incorreta (ou, no mínimo, incompleta), ou o programa contém um bug. / p>     

por 30.06.2016 / 09:17

Tags