AWK 関数を使用して例を作成したのですgetline
が、混乱しています。
$ cat in
foo
bar
baz
$ awk '{ getline tmp; print tmp; print $0 }' in
bar
foo
bar
baz
次の行を という名前の変数に読み込んでいますが、出力の最初の 2 行で確認されるように、tmp
この変数は変更されません。$0
bar
foo
これは以下の表から確認できる。AWK プログラミング言語62ページ:
NR
組み込みのおよび は、これまでに読み取られた行数を表すことはわかっています。これが何が起こっているかを理解するための鍵だと思いますが、パス中に変更すると将来のパスにどのような影響が及ぶのFNR
かわかりません。NR
次の 2 行は次のようになると予想していました。
baz
bar
なぜなら、2 回目のパスで$0 == bar
、tmp == baz
.
そして、次の 2 行は実際には 1 行だけになると思っていました。
baz
なぜなら、3 回目のパスで$0 == baz
、tmp == null
.
したがって、期待される出力は次のようになります。
bar
foo
baz
bar
baz
NR
awk ループ内でどのように変化するかを理解することが、この出力を理解する鍵になると思います。
- 予想した出力が間違っている理由を説明していただけますかそして実際の出力が正しいのはなぜですか?
私は走っていawk version 20070501
ますmacOS 10.12.1
答え1
あなたが見逃しているのは、設定においてNR
、getline
事実上消費する行。したがって、2 回目の呼び出しでは、はbar
すでになくなっており になって$0
いますbaz
。getline
別の行を読み取ろうとしますが失敗します。また、 の値はtmp
変更されません (つまり、 と等しくなりますbar
)。
の戻り値を確認すると理解しやすくなるかもしれませんgetline
:
awk '{ if ((getline tmp) > 0) print tmp; print $0 }' in
bar
foo
baz
答え2
いわば、全体像を見れば明らかになるはずです。awk プログラムは、プログラム テキストのループであり、1 行を読み取り、その行のプログラムを実行します。プログラム内の行を読み取る場合、周囲のループはこの行を参照できません。すでに消費されているためです。
たとえば、あなたのプログラム
{ getline tmp; print tmp; print $0 }
次のように書くことができる。
BEGIN {
while (getline $0) {
getline tmp; print tmp; print $0
}
}
ブロックBEGIN
はプログラムの先頭で 1 回実行され、ここではプログラムは他に何も行いません。もちろん、これは awk コードの記述方法としては非常に非慣用的です。
ここで何が起こるかは明らかです:
- 1行目から
$0
最初のgetline
tmp
2行目を2番目に読んでくださいgetline
- 印刷し
tmp
てから$0
、つまり 2 行目を印刷してから 1 行目を印刷します。 - 次の行のペアでも繰り返します。4 行目を印刷してから 3 行目を印刷します。
行数が奇数の場合、最後の行は を通過して失敗しますがgetline $0
、getline tmp
戻りステータスをチェックしていないため、変更tmp
されずにそのまま残り、最後から 2 番目の行が再度印刷されることになります。