基礎

基礎 の AWK

1個の演習

基礎について

ここでは、_言語_のことをAWK、AWKプログラムを解釈する_実行ファイル_のことを**awkまたはgawk**と呼びます。

パターンとアクション

AWKプログラムは、パターンとアクションのペアで構成されます。

pattern1 { action1 }
pattern2 { action2 }
...

パターンには、入力と照合する正規表現を指定できます。 真偽値になる任意の式を指定することもできます。

アクションは、1つ以上のAWKコマンドです。 アクションを囲む波括弧は必須です。

パターンの結果が_true_なら、対応するアクションが実行されます。

レコードとフィールド

AWKは入力を一連のレコードとして解析します。 各レコードは、0個以上のフィールドに分割されます。

デフォルトの動作は次のとおりです。

  • 改行を「レコード区切り」として入力をレコードに分割するので、_各行_が1つのレコードになります。
  • 空白を「フィールド区切り」としてレコードをフィールドに分割するので、_各単語_が1つのフィールドになります。

パターンとアクション(続き)

パターンは省略できます。その場合、アクションは_すべての入力レコード_に対して実行されます。

アクションは省略できます。その場合、デフォルトのアクションは現在のレコードを出力することです。

特殊なパターン

よく使われる特殊なパターンが2つあります。

  • BEGINは、入力が読み込まれる前に、対応するアクションを実行します。
  • ENDは、すべての入力を読み込んだ後に、対応するアクションを実行します。

フィールド変数

フィールドは$1、$2、$3のように参照します。

現在のレコードは$0です。

Caution

はっきり言っておくと、これらは厳密には「変数」ではありません。 $は、指定したフィールド番号の値を取得する_演算子_と考えることができます。 これについては、後の概念で詳しく見ていきます。

ほかにもよく使われる組み込み変数を紹介します。

入力の解析を制御する組み込み変数

  • RSは入力のレコード区切りです。 前述のとおり、デフォルト値は改行です。
  • FSは入力のフィールド区切りです。

これらの変数は、BEGINアクションブロックで設定することが多いです。

情報を伝える組み込み変数

これらの変数は、プログラムの実行中にAWKによって自動的に設定されます。

  • NFは、現在のレコードのフィールド数を保持します。
    • 最後のフィールドの値を取得するには、$NFを使います。
  • NRは、現在のレコード番号を保持します。
    • 複数の入力ファイルを処理しているとき、NRはそれまでに処理したレコードの総数を保持します。
  • FNRは、現在の入力ファイルにおける現在のレコード番号を保持します。
    • NRとFNRの違いを説明するために、よく使われるAWKのイディオムを紹介します。
      NR == FNR {action}
      
      これは「累積のレコード番号が、現在のファイルのレコード番号と等しいなら」という意味です。 これが成り立つのは、_最初の入力ファイル_のレコードだけです。

真偽の扱い

AWKは、Cと同じ真偽の考え方を使います。

  • 数値の0は偽です。
  • それ以外の数値は真です。

AWKはテキスト処理言語なので、真偽値は文字列にも拡張されています。

  • 空文字列""は偽です。
  • 空でない文字列は真です。
Note

AWKは、Cと同じ真偽の考え方を使います

AWKは1970年代にベル研究所で生まれました。Cが生まれたのと同じ環境です。 CはAWKの構文に大きな影響を与えました。

Caution

気をつけたいちょっとした落とし穴

  • 数値の0は偽です。
  • 空でない文字列"0"は真です!

AWKのデータ型については、後の概念でさらに詳しく見ていきます。

コメント

コメントは#で始まり、行の終わりまで続きます。

awkに入力を渡す方法

awkは、ファイルまたは標準入力から入力を読み込むことができます。 次のどの方法でも動作します。

awk '/regex/ {print $1}' file1 file2 ...

awk '/regex/ {print $1}' < file

some_command_here | awk '/regex/ {print $1}'

例

Unix系のシステムでは、/etc/passwdにユーザーに関する情報が含まれています。 各ユーザーは1行ずつ記述され、フィールドはコロンで区切られています。

ユーザー名を一覧表示するには、次のようにします。

awk '
    BEGIN { FS = ":" }
    { print $1 }
' /etc/passwd

{print $1}というアクションにはパターンがないので、すべてのレコードに対して実行されることに注目してください。

出力を、ログインシェルとしてbashを使っているユーザーだけに絞りたい場合は、次のようにします。

awk '
    BEGIN { FS = ":" }
    $7 == "/bin/bash" { print $1 }
' /etc/passwd

さらにいくつかの例

ここでは、他の一般的なUnixコマンドと同じ結果を生み出すawkプログラムをいくつか紹介します。

  • ファイルを表示する

    cat file.txt
    
    awk '1' file.txt
    
  • ファイル内のパターンを検索する

    grep 'foo.*bar' file.txt
    
    awk '/foo.*bar/' file.txt
    
  • ファイルの先頭の数行だけを表示する

    head -n 20 file.txt
    
    awk '
        1
        NR == 20 {exit}
    ' file.txt
    
  • ファイル内のテキストを置換する

    sed 's/foo/bar/' file.txt
    
    awk '{sub(/foo/, "bar")};1' file.txt
    # or more readably
    awk '
        {
            sub(/foo/, "bar")
            print
        }
    ' file.txt
    
GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

基礎を学習する