awkではいつBEGINが必要ですか?

awkではいつBEGINが必要ですか?

次のコマンドは同じ答えを生成します。

tail -n 1 ~/watchip.sh.csv | awk 'BEGIN { FS = "," } ; { print $1 }' 
tail -n 1 ~/watchip.sh.csv | awk '{ FS = "," } ; { print $1 }'

編集:この質問を投稿した後、上記の2つのコマンドが同じ答えを生成するという私の主張が間違っていることがわかりました。少なくとも一般的にはそうではありません。したがって、上記のコマンドはBEGINステートメントが必要な場合の例のようです。混乱させて申し訳ありません。

私は経験豊富なawkユーザーではありませんが、この製品を使用して文書を読んでより良い使い方をするよう努めています。しかし、私がBEGINとENDで読んだことはすべてあいまいです(私にとってはほとんど理解されていません)。それはおそらく、私がawk非常に限られた状況でのみ使用したからです。

BEGIN文がいつであるかを簡単に説明できる人はいますか?必須存在するawk

答え1

BEGINandEND句は、実際に何かをしたいときに主に使用されます。awk今後そして後ろにファイルの実際の処理は別々に行われます。したがって、このロジックを使用すると、そのロジックのステートメント/アクションは、指定された入力ファイルに対して一度だけ実行されます。

通常、どのような種類のタスクが実行されますかBEGIN

  1. 行入力を分割するために使用される特殊変数(たとえば、入力フィールドと出力フィールドの区切り文字)を初期化しますFSOFS常に構文を使用してこれらの特殊変数を定義したり、-v FS=正規表現演算子で定義したりできますが、そうすればはるかに-F','読みやすくなります。あなたの例で判断すると、入力ファイルの各行の変数を初期化するため、{ FS="," }本文でこれを定義する必要があるのはやや重複します。awkたとえば、行にn行が含まれていると、初期化がn回発生します。

    echo "1,2,3" | awk 'BEGIN {FS=OFS=","} {print $1}'
    
  2. スクリプト本文で生成された出力のカスタムヘッダー行を定義しますawk。たとえば、前の例では、最初の列の値を印刷していることを示すヘッダーを印刷したいと思いました。

    echo "1,2,3" | awk 'BEGIN {FS=OFS=","; print "First column values only"} {print $1}'
    
  3. (オプション - 読みやすくするため) - プログラム本文内で使用される変数を初期化することもできます。推奨されませんが、変数の初期化を動的に処理するため、変数の状態を理解するのにawk役立ちます。BEGIN

    echo "1,2,3" | awk 'BEGIN {FS=OFS=","; counter = 0; } $1 == "1" { counter++ }'
    

通常、どのような種類のタスクが実行されますかEND

  1. コマンド本文で処理された行数を追跡しますawk。一般的な慣用語は、ファイルの行数を追跡することです。各行が処理されるたびに増加する実行カウンタである特殊awk変数を使用します。NRつまり、最初の行変数の値は 1 になってから増加します。しかし、この場合、ファイルの総行数をどのように印刷できますか?print NRファイルの処理中に現在行番号を印刷するため、ファイル本文ではこれを行う方法はありません。awkたとえば、以下の最初のスニペットは機能しません。それで、ENDこれはその中のステートメントが次のようなときに起こります。後ろにファイル処理が完了しました。したがって、同じ方法で印刷すると、保存されたEND最後の値が印刷されます。NR

    printf '1\n2\n\3' | awk '{print "total="NR}'
    total=1
    total=2
    total=3
    printf '1\n2\n\3' | awk 'END{print "total="NR}'
    total=3
    
  2. ヘッダ情報を印刷するセクションと同様に、BEGINこの時点ですべてのファイル処理が完了するため、文字列と情報をまとめて印刷できます。

この文書効果的なAWKプログラミングツールをよりよく理解するのに最適なリソースです。

答え2

「効果的なAWKプログラミング」は私にとって非常に役立ちました。

awkはパターンとアクションで構成されるルールと連携し、どちらも省略できますが、どちらも省略することはできません。 BEGINとENDはパターンで、{...}は演算です。パターンが存在しない場合、またはパターンが一致しない場合、操作が実行されます。

awk 'BEGIN      {FS=OFS=","}      {print $1}'
     ^pattern + ^action           ^ action without pattern

awk '{ FS = "," }         ;        { print $1 }'
     ^action without pattern       ^ another action without pattern

一般的なawkプログラムでは:

  • BEGIN{...}はレコードの前に実行されるため、ここで必要なものをすべて初期化できます。
  • 各レコードはメインループであるパターン{...}を実行します。
  • END{...}は最後のレコード以降に実行されます。メインループが完了し、すべてのデータがあなたの手にあるので、あなたが望むものは何でもすることができます。

関連情報