AWKで「getline」はどのように機能しますか?

AWKで「getline」はどのように機能しますか?

AWK関数を使用して例を作成しましたが、getline混乱しています。

$ cat in
foo
bar
baz
$ awk '{ getline tmp; print tmp; print $0 }' in
bar
foo
bar
baz

出力の最初の2行で確認されているように、tmpwhich will notchangeという変数で次の行を読み込んでいます。$0

bar
foo

これは以下の表で確認されますAWKプログラミング言語ページ 62:

ここに画像の説明を入力してください。

私も知っていて、NR組み込みFNR関数はこれまでに読んだ行数を表します。これが何が起こっているのかを理解するための鍵だと思いますが、1つのNRパスの変更が今後のパスにどのような影響を与えるかを混乱させます。

次の2行は次のとおりです。

baz
bar

2番目のパス$0 == barではtmp == baz

その後、次の2行は実際には1行になると予想されます。

baz

なぜなら3番目$0 == baztmp == null

だから私の予想結果は次のとおりです。

bar
foo
baz
bar
baz

私はawkのwhileループの変化を理解することがNRこの出力を理解する鍵だと思います。

  • 予想される出力が間違っている理由を説明できますか?そして実際の出力が正しい理由は何ですか?

私はawk version 20070501走っていますmacOS 10.12.1

答え1

私の考えであなたが逃したのはNR実際に設定getlineから消費するワイヤー。したがって、2番目の呼び出しではbarisが消え、$0isはbaz別のgetline行を読み取ろうとしましたが失敗し、isの値はtmp同じままです(つまり、bar)。

戻り値を確認すると、理解しやすくなりますgetline

awk '{ if ((getline tmp) > 0) print tmp; print $0 }' in
bar
foo
baz

答え2

大きな絵を見ると明確になると言えば十分です。 awk プログラムは、1 行を読み、その行でプログラムを実行するプログラムテキストの周りのループです。プログラム内で1行を読み取ると、周囲のループでその行を見ることはできません。その行はすでに使用されています。

例えば、プログラム

{ getline tmp; print tmp; print $0 }

次のように書くことができます

BEGIN {
    while (getline $0) {
        getline tmp; print tmp; print $0
    }
}

このBEGINブロックは、プログラムの開始時にプログラムが他の操作を実行しないときに一度実行されます。確かにこれはawkコードを書く非常に一般的な方法です。

ここで何が起こっているのかを明確にする必要があります。

  • $01行から1行まで読むgetline
  • tmp2行から2行まで読むgetline
  • tmp次に印刷$0、つまり行2を印刷してから、行1を印刷します。
  • 次の行のペアについて繰り返します。 4行が印刷され、3行が印刷されます。

奇数行の場合、最後の行が通過してgetline $0失敗getline tmpしますが、戻り状態を確認せずにtmpそのまま残り、最後の2行目を再印刷します。

関連情報