AWK ENDアクションはマニュアルページの$ 0に最後の行をロードしますか?

AWK ENDアクションはマニュアルページの$ 0に最後の行をロードしますか?

私は読んだもう一つの答え使用方法について説明します。AWK出力の最後の行を確認してください。

$ seq 42 | awk 'END { print }'
42

したがって、ENDブロックが実行されると最後の行が$0

最初の行がBEGINブロックにロードされなかったので、これは私を驚かせました。

$ seq 42 | awk 'BEGIN { print }'
#=> blank
  • この動作はどこにも文書化されていますか? (検索してみるとマニュアルページしかし、何も見つかりませんでした)

答え1

このBEGINブロックは入力が処理される前に実行されるため、$0まだ初期化されていません。

ブロックENDは何もしません。$0最後の値を保持します。 AWKスクリプトでは、AWKはすべての入力を1行ずつ読み込み、通常のフィールド分割処理(割り当て$0など)を実行しますが、一致するブロックを見つけることができないため、これは最後に読み取った行だけです。

seq 42 | awk '{ $0 = "21" } END { print }'

END42ではなく21を出力するので、「ブロックの実行中に最後の行をロードする」ことはありません$0

これは文書化されていません。gawk(1)マンページですが、次の文書に文書化されています。mawk(1)(明らかにAWK実装の場合):

同様に、ジョブの開始時に、ENDおよび$0フィールドの値はNF最後のレコードで変更されていません。

GNU AWKのマニュアルは次のとおりです。この行動に言及する:

実際、すべてのBWK awk、、、mawkおよび値はルールで使用するようにgawk予約されています。$0END

「BWK」はawkBrian Kernighanawkの作品です。「本物awkFIXES;文書に記載されているように、2005年にこの動作を実装しました。

2005年4月24日: posixの要求に応じてENDブロックにet alの値を保持するようにlib.c修正されました。$0レポートとコードを提供してくれたhavard eidnesに感謝します。

この変化は以下から見ることができる。「真のawk」歴史。最新バージョンのBWKはawkGNU AWKと同じように動作します。

$ echo three fields here | ./awk '{ $0 = "one" } END { print $0 " " NF }'
one 1
$ echo three fields here | ./awk 'END { $0 = "one"; print $0 " " NF }'
one 1

答え2

~によるとGNU awk マニュアル$0、ENDルールに何を含めるべきかは少し不明です。 POSIXの要件NF 「[それの]価値は維持されるべきです」(*)、しかし言及されていません$0

$0ほとんどの場合、監督のために論理的に維持されなければならないと考えても、標準では維持されるとは言いません。実際、すべてのBWK awk、mawk、およびgawkはルールに使用する$0値を保持します。ENDただし、他のいくつかの実装とUnix awkの多くの以前のバージョンはそれをサポートしていません。

ある意味では、これらの行動は論理的だと思います。必要に応じて、最後の履歴に簡単にアクセスできるようにブロックを$0終了します。END最初のレコードは簡単にアクセスできるため、NR == 1 {...}特別なキーワードは必要ありません。一方、 BEGIN最初のレコードをロードする前にブロックを実行すると、最初のレコードに合わせてブロックを設定またはFSアクティブRS化できます。

(*その意味が何であるかについてはコメントを参照してください。)

関連情報