- awkは、パターンとアクションのルールを適用することで、他のプログラムからの出力をフィルタリングおよび操作するために使用されます。
- awkはテキストから特定のフィールドを出力したり、フィールド間の区切り文字を変更したり、組み込み関数を用いてさまざまなアクションを実行したりできます。
- awkは、作成者のアルフレッド・アホ、ピーター・ワインバーガー、ブライアン・カーニハンにちなんで名付けられました。
Linuxでは、awk
はコマンドラインのテキスト操作ダイナモであり、強力なスクリプティング言語でもあります。その最も優れた機能のいくつかを紹介します。
awkの名前の由来
awk
コマンドは、1977年にオリジナルバージョンを執筆した3人のイニシャル、アルフレッド・アホ、ピーター・ワインバーガー、ブライアン・カーニハンを使用して名付けられました。この3人は、伝説的なAT&Tベル研究所のUnixの神殿出身です。それ以降多くの人々が貢献したおかげで、awk
は進化を続けてきました。
コマンドライン用の完全なスクリプティング言語であり、テキスト操作ツールキットでもあります。この記事を読んで興味が湧いたら、awk
とその機能の詳細を確認できます。
awkの用途:ルール、パターン、アクション
awk
は、他のプログラムや関数の出力をフィルタリングおよび操作するために使用されます。awk
は、パターンとアクションで構成されたルールを含むプログラムで動作します。awkが実行するアクションは、パターンに一致するテキストで実行されます。パターンは中括弧({}
)で囲まれます。パターンとアクションを合わせてルールを形成します。awk
プログラム全体は、シングルクォート('
)で囲まれます。
最も単純なタイプのawk
プログラムを見てみましょう。パターンがないため、入力されたすべての行のテキストに一致します。つまり、アクションはすべての行で実行されます。who
コマンドの出力に使用します。
who
の標準出力が次のとおりです:
who
その情報をすべて必要とするのではなく、アカウントの名前だけを確認したい場合があります。who
の出力awk
にパイプしてから、awk
に最初のフィールドのみを出力するように指示できます。
デフォルトで、awk
はフィールドを、空白、行頭、または行末で囲まれた文字列とみなします。フィールドはドル記号($
)と数字で識別されます。そのため、$1
は最初のフィールドを表し、print
アクションで最初のフィールドを出力するために使用します。
次のように入力します:
who | awk '{print $1}'
awk
は最初のフィールドを出力し、残りの行を破棄します。
好きなだけ多くのフィールドを出力できます。区切り文字としてカンマを追加すると、awk
は各フィールド間にスペースを出力します。
次のように入力して、ログインした時刻(フィールド4)も出力します:
who | awk '{print $1,$4}'
特別なフィールド識別子がいくつかあります。これらは、テキストの全行とテキスト行の最後のフィールドを表します:
- $0:テキストの全行を表します。
- $1:最初のフィールドを表します。
- $2:2番目のフィールドを表します。
- $7:7番目のフィールドを表します。
- $45:45番目のフィールドを表します。
- $NF:「フィールドの数」を表し、最後のフィールドを表します。
次のように入力して、デニス・リッチーの短い引用が含まれる小さなテキストファイルを表示します:
cat dennis_ritchie.txt
awk
を使用して、引用の最初のフィールド、2番目のフィールド、最後のフィールドを出力します。ターミナルウィンドウで折り返されていますが、これは単一のテキスト行であることに注意してください。
次のコマンドを入力します:
awk '{print $1,$2,$NF}' dennis_ritchie.txt
テキスト行の18番目のフィールドが「simplicity.」であることはわかりませんし、気にしません。わかっているのはそれが最後のフィールドであるということだけであり、$NF
を使用してその値を取得できます。ピリオドは、フィールドの本文の別の文字とみなされます。
awk出力に出力フィールド区切り文字を追加する
デフォルトのスペース文字ではなく、特定の文字をフィールド間に印刷するようにawk
に指示することもできます。date
コマンドのデフォルト出力は少し特殊であり、時刻がその真ん中に配置されるためです。ただし、次のように入力して、awk
を使用して必要なフィールドを抽出できます:
date
date | awk '{print $2,$3,$6}'
OFS
(出力フィールド区切り文字)変数を使用して、月、日、年間に区切り文字を配置します。以下ではコマンドを中括弧({}
)ではなく、シングルクォート('
)で囲んでいることに注意してください:
date | awk 'OFS="/" {print$2,$3,$6}'
date | awk 'OFS="-" {print$2,$3,$6}'
BEGINとENDのルール
BEGIN
ルールは、テキスト処理が開始される前に1回実行されます。実際、awk
がテキストを読み取る前ですら実行されます。END
ルールは、すべての処理が完了した後に実行されます。複数のBEGIN
ルールとEND
ルールを設定でき、順に実行されます。
BEGIN
ルールの例では、以前に使用したdennis_ritchie.txt
ファイルからの引用全体を、その上にタイトルを付けて出力します。
これを行うには、次のコマンドを入力します:
awk 'BEGIN {print "Dennis Ritchie"} {print $0}' dennis_ritchie.txt
BEGIN
ルールには、独自の中括弧({}
)で囲まれた独自のアクションセットがあることに注意してください。
この同じ手法を、以前に使用したコマンドでwho
からawk
に出力をパイプする場合に使用できます。これを行うには、次のように入力します:
who | awk 'BEGIN {print "Active Sessions"} {print $1,$4}'
入力フィールド区切り文字
awk
で空白文字を使用してフィールドを区切らないテキストを処理する場合は、テキストでフィールド区切り文字として使用される文字を指定する必要があります。たとえば、/etc/passwd
ファイルでは、コロン(:
)を使用してフィールドを区切っています。
そのファイルと-F
(区切り文字列)オプションを使用して、awk
にコロン(:
)を区切り文字として使用するように指示します。awk
にユーザーアカウントの名前とホームフォルダーを出力するように指示するには、次のように入力します:
awk -F: '{print $1,$6}' /etc/passwd
出力には、ユーザーアカウントの名前(またはアプリケーションまたはデーモンの名前)とホームフォルダー(またはアプリケーションの場所)が含まれています。
awkにパターンを追加する
通常のユーザーアカウントのみを対象としている場合、パターンをprintアクションに含めて他のすべてのエントリをフィルタリングできます。ユーザーID番号は1,000以上であるため、その情報に基づいてフィルタを適用できます。
第3フィールド($3
)に1,000以上の値が含まれる場合にのみprintアクションを実行するには、次のように入力します:
awk -F: '$3 >= 1000 {print $1,$6}' /etc/passwd
パターンは、関連付けられているアクションの直前に配置する必要があります。
BEGIN
ルールを使用して、小さなレポートにタイトルを付けることができます。タイトル文字列に改行文字を挿入するには、(\n
)表記を使用して次のように入力します:
awk -F: 'BEGIN {print "User Accounts\n-------------"} $3 >= 1000 {print $1,$6}' /etc/passwd
パターンは本格的な正規表現であり、awk
の素晴らしさの1つです。
マウントされたファイルシステムのUniversally Unique Identifier(UUID)を表示するとします。/etc/fstab
ファイルで文字列「UUID」の出現を検索すると、その情報が返されるはずです。
コマンドで検索パターン「/UUID/」を使用します:
awk '/UUID/ {print $0}' /etc/fstab
「UUID」のすべての出現を検索し、それらの行を出力します。print
アクションがなくても同じ結果が得られたはずです。デフォルトのアクションはテキストの全行を出力するからです。ただし、明確にするために、明示的にすることがよくあります。スクリプトや履歴ファイルを見ると、自分自身の手がかりを残したことを嬉しく思います。
最初に発見された行はコメント行で、「UUID」文字列はその真ん中にありますが、awk
はまだそれを発見しました。正規表現を調整して、awk
に「UUID」で始まる行のみを処理するように指示できます。これを行うには、行頭トークン(^
)を含む次のように入力します:
awk '/^UUID/ {print $0}' /etc/fstab
いいですね!これで、本物のマウント命令だけが表示されます。出力をさらに絞り込むには、次のように入力して、表示を最初のフィールドに制限します:
awk '/^UUID/ {print $1}' /etc/fstab
このマシンに複数のファイルシステムがマウントされていた場合、それらのUUIDのきちんとした表が得られます。
awkの組み込み関数の使用方法
awk
には、コマンドラインとスクリプトの両方から独自のプログラムで呼び出して使用できる関数が数多くあります。少し調べれば、非常に有益であることがわかります。
関数を呼び出す一般的な手法を示すために、数値的な関数を見てみましょう。たとえば、次のコマンドは625の平方根を出力します:
awk 'BEGIN { print sqrt(625)}'
このコマンドは、0(ゼロ)と-1(数学定数、円周率になる)の逆正接を出力します:
awk 'BEGIN {print atan2(0, -1)}'
次のコマンドでは、atan2()
関数の結果を出力する前に変更します:
awk 'BEGIN {print atan2(0, -1)*100}'
関数は、パラメータとして式を受け入れることができます。たとえば、25の平方根を求める込み入った方法を次に示します:
awk 'BEGIN { print sqrt((2+3)*5)}'
awkスクリプト
コマンドラインが複雑になったり、再び使用したいルーチンを開発したりした場合は、awk
コマンドをスクリプトに転送できます。
このスクリプトの例では、次のすべてを実行します:
- シェルに、スクリプトを実行するために使用する実行可能ファイルを指示します。
awk
を準備して、FS
フィールド区切り文字変数を使用して、コロン(:
)で区切られたフィールドを含む入力テキストを読み取ります。OFS
出力フィールド区切り文字を使用して、awk
に出力を区切るためにコロン(:
)を使用するように指示します。- カウンターを0(ゼロ)に設定します。
- 各テキスト行の2番目のフィールドを空白値に設定します(常に「x」なので、表示する必要はありません)。
- 変更された2番目のフィールドでその行を出力します。
- カウンターを増やします。
- カウンターの値を出力します。
スクリプトを以下に示します。
BEGIN
ルールは準備手順を実行し、END
ルールはカウンター値を表示します。中間ルール(名前もパターンもないため、すべての行に一致します)は、2番目のフィールドを変更し、その行を出力し、カウンターを増やします。
スクリプトの最初の行は、シェルにスクリプトを実行するために使用する実行可能ファイル(この例ではawk
)を指示します。また、-f
(ファイル名)オプションをawk
に渡します。これは、処理するテキストがファイルから取得されることを通知します。スクリプトを実行するときにファイル名をスクリプトに渡します。
スクリプトをテキストとして以下に含めたので、切り取って貼り付けることができます:
#!/usr/bin/awk -fBEGIN { # set the input and output field separators FS=":" OFS=":" # zero the accounts counter accounts=0}{ # set field 2 to nothing $2="" # print the entire line print $0 # count another account accounts++}END { # print the results print accounts " accounts.\n"}
これをomit.awk
という名前のファイルに保存します。スクリプトを実行可能にするには、chmod
を使用して次のように入力します:
chmod +x omit.awk
これで、スクリプトを実行して/etc/passwd
ファイルをスクリプトに渡します。これは、スクリプト内のルールを使用して、awk
が処理するファイルです:
./omit.awk /etc/passwd
ファイルが処理され、各行が以下に示すように表示されます。
2番目のフィールドの「x」エントリは削除されましたが、フィールド区切り文字は残っていることに注意してください。行がカウントされ、合計が出力の一番下に示されます。
awkはAwkwardの略ではない
awk
は、Awkwardの略ではなく、エレガンスの略です。処理フィルターやレポートライターとして説明されています。より正確に言えば、それらの両方、あるいはむしろその両方のタスクに使用できるツールです。awk
は、ほんの数行で、従来の言語で広範囲にわたるコーディングを必要とするものを実現します。
その力は、処理するテキストを選択するパターンと、処理を定義するアクションを含むルールという単純な概念によって制御されます。
コメントする