awk의 일관되지 않은 동작

awk의 일관되지 않은 동작

다음과 같은 텍스트 파일이 있습니다 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

다음 명령을 실행하면 다음과 같은 결과가 나타납니다.

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

정규식이 의 왼쪽에 있으면 어떤 일이 발생하는지 이해합니다 ~.

0하나 또는 빈 문자열(null?)이 일치하는 것으로 간주된다는 것을 알고 있습니다 .

내가 이해하지 못하는 것은 유언장 이 때로는 0일치하고 때로는 일치하지 않는 이유입니다. 이전에 처리된 모든 레코드와 관련이 있는 것처럼 보이지만 awk각 입력 레코드는 독립적으로 처리되므로 서로 영향을 미치지 않아야 한다고 생각합니다(적어도 일부 변수 할당이나 다른 조작 없이는).

편집: 중요한 경우 GNU Awk 4.1.3을 사용하고 있습니다.

답변1

(g)awks 매뉴얼 페이지에서:

~ !~        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.

명시적으로 금지된 방식으로 사용하면 어떤 일이 발생할 것으로 예상합니까?

답변2

사실 이것은 흥미로운 질문이다. @tink는 코드가 예상대로 작동하지 않는 이유를 지적했지만 이는 문제가 아닙니다. 문제는 " 0때로는 왜 일치하는가"입니다.

(/foo/ ~ $1)그것이 실제로 의미되는 경우 해당 줄이 포함되어 있으면 평가되고 , (($0 ~ /foo/) ~ $1)그렇지 않으면 ($0 ~ /foo/)평가됩니다 . 따라서 (대부분) . 을 평가하고 있으며 입력 줄이 비어 있으면 NULL 정규식은 항상 일치합니다 . 입력 행 이 이면 합계 도 true입니다. 예를 들어 입력 행이 이면 도 마찬가지이며 true 가 아니어야 합니다. 그러나 일치 여부를 확인하기 전에 로 변환될 가능성이 높습니다 .1foo00 ~ $1$1 == ""0$10 ~ 0000$10 ~ 0000000

그러나 불행하게도 이 설명이 모든 상황을 다루지는 않습니다.

사례 1

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

이것은 정확히 예상한 대로입니다.

사례 2

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

이는 0이 여러 개 해석되는 한 예상되는 현상입니다 0. 하지만 지금은 다음과 같습니다.

사례 3

0 <-- found match
a
00 0
0

이것은 그렇게 간단하게 설명할 수 없습니다. 일치가 실패한 후에는 0으로의 변환이 발생하지 않는 것처럼 보이며 일치해야 하는 후속 행도 발생하지 않습니다.

사례 4

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

무슨 일이 일어나든 또 다른 실패한 일치는 동작을 정상으로 재설정하는 것처럼 보이며 awk일치는 다시 예상대로 작동합니다.

전체적으로 GNU 매뉴얼 페이지의 설명( awk그런데 정보 페이지의 일부가 아님)이 올바르지 않거나(또는 적어도 불완전) 프로그램에 버그가 포함되어 있습니다.

관련 정보