AWK関数を使用して例を作成しましたが、getline
混乱しています。
$ cat in
foo
bar
baz
$ awk '{ getline tmp; print tmp; print $0 }' in
bar
foo
bar
baz
出力の最初の2行で確認されているように、tmp
which will notchangeという変数で次の行を読み込んでいます。$0
bar
foo
これは以下の表で確認されますAWKプログラミング言語ページ 62:
私も知っていて、NR
組み込みFNR
関数はこれまでに読んだ行数を表します。これが何が起こっているのかを理解するための鍵だと思いますが、1つのNR
パスの変更が今後のパスにどのような影響を与えるかを混乱させます。
次の2行は次のとおりです。
baz
bar
2番目のパス$0 == bar
ではtmp == baz
。
その後、次の2行は実際には1行になると予想されます。
baz
なぜなら3番目$0 == baz
とtmp == null
。
だから私の予想結果は次のとおりです。
bar
foo
baz
bar
baz
私はawkのwhileループの変化を理解することがNR
この出力を理解する鍵だと思います。
- 予想される出力が間違っている理由を説明できますか?そして実際の出力が正しい理由は何ですか?
私はawk version 20070501
走っていますmacOS 10.12.1
答え1
私の考えであなたが逃したのはNR
実際に設定getline
から消費するワイヤー。したがって、2番目の呼び出しではbar
isが消え、$0
isは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コードを書く非常に一般的な方法です。
ここで何が起こっているのかを明確にする必要があります。
$0
1行から1行まで読むgetline
tmp
2行から2行まで読むgetline
tmp
次に印刷$0
、つまり行2を印刷してから、行1を印刷します。- 次の行のペアについて繰り返します。 4行が印刷され、3行が印刷されます。
奇数行の場合、最後の行が通過してgetline $0
失敗getline tmp
しますが、戻り状態を確認せずにtmp
そのまま残り、最後の2行目を再印刷します。