基本

基本

学習演習

はじめに

基礎

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

パターンとアクション

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

pattern1 { action1 }
pattern2 { action2 }
...

パターンには、入力と照合する正規表現パターンを指定できます。 trueかfalseになる任意の式でもかまいません。

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

パターンの結果がtrueの場合、対応するアクションが評価されます。

レコードとフィールド

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

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

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

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

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

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

特別なパターン

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

  • BEGINは、入力が消費される前に対応するアクションを評価します。
  • ENDは、すべての入力が消費された後に対応するアクションを評価します。

フィールド変数

フィールドは$1、$2、$3などで参照します。

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

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

入力の解析を制御する組み込み変数
  • RSは入力のレコード区切りです。 前述のとおり、デフォルト値は改行です。
  • FSは入力のフィールド区切りです。

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

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

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

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

真偽の扱い

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

  • 数値の0はfalseです。
  • それ以外の数値はすべてtrueです。

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

  • 空文字列""はfalseです。
  • 空でない文字列はすべてtrueです。

コメント

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

例

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

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

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

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

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

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

説明

昔々、サイバースペースと呼ばれる賑やかな都市がありました。 サイバースペースはデジタルの大都市で、何百万人もの住民が毎日ログインしたりログアウトしたりしていました。 これらすべてのユーザーを管理するために、サイバースペースには/etc/passwdという特別なファイルがありました。

/etc/passwdファイルは、この都市の電話帳のようなものでした。 システムにアカウントを持つすべてのユーザーと、それぞれのユーザーに関するいくつかの重要な情報が記載されていました。

n フィールド
1 ユーザー名
2 パスワード(「x」は、実際のパスワードがセキュリティのため別の場所に保存されていることを示します)
3 UID、一意の数値のユーザーID
4 GID、一意の数値のグループID(通常はUIDと同じです)
5 ユーザー情報(通常はユーザーのフルネームですが、他の情報を含むこともあります)
6 ホームディレクトリ
7 ログインシェル

各フィールドはコロン文字で区切られています。 典型的なエントリーは次のとおりです。

glennj:x:1010:1010:Glenn Jackman:/home/glennj:/usr/local/bin/fish

このファイルはシステム管理者のチームによって管理され、新しいアカウントの作成、既存のアカウントの更新、古いアカウントの削除を担当していました。 システム管理者はサイバースペースの門番であり、許可されたユーザーだけがシステムにアクセスできるようにしていました。

ある日、アレックスという新しいシステム管理者がチームに加わるために雇われました。 アレックスはその仕事を引き受けることに胸を躍らせ、すぐに/etc/passwdファイルの仕組みを隅々まで学びました。 システムに新しいユーザーを追加する方法、ユーザー情報を更新する方法、古いユーザーを削除する方法を学びました。

アレックスが/etc/passwdファイルを扱っていると、何か奇妙なことに気づきました。 何人かのユーザーは、奇妙で変わったホームディレクトリを持っていました。 あるユーザーのホームディレクトリは/dev/nullに設定され、別のユーザーのホームディレクトリは存在しない奇妙なパスに設定されていました。

アレックスは、これらのユーザーが実在の人物ではなく、ハッカーによって作成された偽のアカウントであることに気づきました。 ハッカーはシステムの脆弱性を悪用する方法を見つけ、サイバースペースへのアクセスを得るためにこれらの偽アカウントを作成していました。

アレックスは、何か行動を起こす必要があると考えました。 アレックスはawkを使って/etc/passwdファイルを分析し、すべての偽アカウントを特定するスクリプトを書きました。 その後、チームの残りのメンバーと協力してこれらのアカウントを削除し、そもそもハッカーがそれらを作成できるようにしていた脆弱性にパッチを当てました。

アレックスがawkを使ったおかげで、チームは偽アカウントを特定して削除し、サイバースペースをみんなにとってより安全な場所にすることができました。 システム管理者たちは引き続き/etc/passwdファイルを管理し、常に最新かつ安全な状態に保ち、許可されたユーザーだけがシステムにアクセスできるようにしていました。

さあ、今度はアレックスのようなシステム管理者になる番です。

Note

この演習を解くために必要になる、AWKの追加の構文をいくつか紹介します。

  • 論理演算子は他の言語とよく似ています。

    演算 例
    AND expr1 && expr2
    OR expr1 || expr2
    NOT ! expr
  • 関数の呼び出しは、見慣れた構文になっています。

    function greet(name) {
        print "Hello", name
    }
    BEGIN {
        greet("Mary")   # prints "Hello Mary"
    }
    

1. ユーザー名を一覧表示する

passwdファイルの各行について、コロンで区切られた最初のフィールドを出力するawkプログラムを書いてください。

2. 行番号を出力する

入力ファイルの各レコードの行番号を出力するawkコマンドを書いてください。 行番号だけを出力し、それ以外の情報は出力しないでください。

3. 無効なホームディレクトリを持つレコードを出力する

サイバースペースでは、「有効な」ホームディレクトリは/homeまたは/rootで始まります。 入力ファイルのうち、無効なホームディレクトリを持つレコードを出力してください。

4. bashを使う有効なユーザーを出力する

ホームディレクトリが有効で、かつログインシェルがbashであるレコードを出力してください。


出典

ChatGPTとの会話
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
AWK Exercism

基本を始める準備はできましたか?

Exercismに登録すれば、3個のコンセプト92個の演習、そして本物の人間によるメンタリングとともに、AWKを学んでマスターできます。すべて無料です。