
この関数
awk
を使用する回答を SO に投稿したところ、奇妙なコメントが寄せられました。getline
ここその答えへのリンクです。
私の回答を投稿した後、あるユーザーが以下のコメントを投稿しました。(彼を批判しているわけではありません。 )
これは良い解決策ではありません。内容に関係なく行を結合し、必要に応じてそれ以上の行を処理しません。また、getline の使用は避けるべきです。
getline
関数を避けるべきだと書かれていますawk
。そこで私の質問は、
getline
awk で関数を使用するのは安全ですか?- どのような状況で使用すべきで、
getline
どのような場合には使用すべきではないのでしょうか? - この関数が予期しない結果を生成する場合は、バグレポートを提出してみませんか?
答え1
ほとんどの人は議論getline
するコーディングスタイル地面。
awk
これは、コードが一度に 1 つのレコードを処理する通常の処理とは異なります。
getline
getline var < "file"
(またはとして使用されていない場合"cmd" | getline
) は、コード ステートメントの途中で次のレコード (次のファイルからのレコードの可能性あり) を取得します。NR、FNR が増加し、FILENAME が変更される可能性があることに気付かなくなることがよくあります。
これを使用するときに忘れてはならないもう 1 つの点は、戻り値を確認することです。EOF の場合は 0 が返され、エラーの場合は <0 が返されます。
つまり、getline
またはではなくif/while (getline) ...
、次のようになります。
if/while ((getline) > 0) { .... }
または:
if/while ((getline < "file") > 0) {...}
の使用法のほとんどは、getline
ステートマシンのようなアプローチを使用することで好転させることができます。
の代わりに:
/pattern/ {getline; print}
これはおそらく間違いで、次のように書くべきです:
/pattern/ && (getline) > 0 {print}
次のようにします:
found_pattern {print; found_pattern=0}
/pattern/{found_pattern=1}
また、この2つがどのように異なるかにも注意してください。パターン連続する 2 行に一致します。
さて、それを知っていれば、getline
は問題ありません。複数のファイルを同時に処理したい場合は が必要ですgetline
が、戻り値を確認することを忘れないでください。
while ((getline a < "a") > 0 && (getline b < "b") > 0) {
....