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

正規表現がの左側にある場合、何が起こるかを理解してください~

01つまたは空の文字列(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。しかし、今は次のようになります。

ケース3

0 <-- found match
a
00 0
0

これはそれほど簡単には説明できません。一致が失敗した後、ゼロへの変換は発生しないように見え、一致する必要がある後続の行も発生しません。

ケース4

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

何が起こっても別の失敗した一致は、動作を正常にリセットするように見え、一致はawk期待どおりに機能します。

全体として、GNUのマニュアルページの説明(awkしかし情報ページの一部ではない)が正しくない(または少なくとも不完全)、プログラムにバグが含まれています。

関連情報