awk コマンドの getline は安全に使用できますか?

awk コマンドの getline は安全に使用できますか?

この関数 awkを使用する回答を SO に投稿したところ、奇妙なコメントが寄せられました。getlineここその答えへのリンクです。

私の回答を投稿した後、あるユーザーが以下のコメントを投稿しました。(彼を批判しているわけではありません。 )

これは良い解決策ではありません。内容に関係なく行を結合し、必要に応じてそれ以上の行を処理しません。また、getline の使用は避けるべきです。

getline関数を避けるべきだと書かれていますawk。そこで私の質問は、

  • getlineawk で関数を使用するのは安全ですか?
  • どのような状況で使用すべきで、getlineどのような場合には使用すべきではないのでしょうか?
  • この関数が予期しない結果を生成する場合は、バグレポートを提出してみませんか?

答え1

ほとんどの人は議論getlineするコーディングスタイル地面。

awkこれは、コードが一度に 1 つのレコードを処理する通常の処理とは異なります。

getlinegetline 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) {
  ....

関連情報