AWKはLinux系ディストリビューションで使用可能なプログラミング言語です。初登場は1979年、ウォークマンが発売された年でした。

AWKはテキストファイルに対して一定の処理を施すために開発されたプログラミング言語です。

本記事ではAWKの使い方について実際の使用例を提示しながら、順を追って説明していきましょう。

AWKでできること

AWKはテキストファイルの中でも一定の法則を持つデータファイルの扱いに長けています。

例えば区切り文字と複数レコードにより構成されたCSVファイル・ログファイルなどです。

AWKはこれらのファイルから必要な情報だけを抽出したり、対象の文字列を編集したりすることができます。

AWKが利用されるのは、主に以下の用途です。

  • CSVファイル操作
  • ログ解析
AWKはsedコマンド・grepコマンドなどと共に、Linux系OSで利用されるテキスト処理技術です。

AWK派生言語解説

AWKはオークと読みます。名前の由来はAWK開発者3人の苗字の頭文字です。

AWKには多くの派生言語が存在しており、定義されている変数・関数や開発目的などが異なっています。

  • awk(元祖AWK)
  • nawk(New AWK)
  • gawk(GNU AWK)
  • mawk(Mike Brennanが実装したAWK)
nawkは新しいバージョンのAWKです。

gawkは本格的に国際化対応されている唯一の派生言語になります。ユーザーが共有ライブラリを作成した機能拡張を行うことも可能です。

マイナーな派生言語も含めると10種類以上も開発されており、どの言語も末尾が「awk」で終わるようになっています。

これらの違いを覚えておく必要はありません。主要な派生言語については様々なサイトでチートシートが公開されています。

AWK動作環境の準備

本格的な解説に入る前に、手元に環境を用意しましょう。本記事ではDockerにて以下の仮想環境を作成し、動作確認を行いました。

  1. # docker run –rm -it centos /bin/bash
  2. $ cat /etc/redhat-release
  3. CentOS Linux release 8.1.1911 (Core)
  4. $ yum -y update
  5. $ yum -y install which

AWKのインストール

一般的なLinuxディストリビューションであればデフォルトでインストールされているでしょう。

  1. $ which awk
  2. /usr/bin/awk

例えばmawkがインストールされていない場合は、以下のようにエラーメッセージが表示される筈です。

  1. $ which mawk
  2. which: no mawk in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin)

AWKがインストールされていない場合は、以下のようなコマンドでインストールを行って下さい。

  1. $ apt -y install mawk
  2. $ yum -y install gawk

AWKのバージョン確認

バージョン確認は以下のコマンドで行います。

  1. $ awk –version
  2. GNU Awk 4.2.1, API: 2.0 (GNU MPFR 3.1.6-p2, GNU MP 6.1.2)
  3. (後略)

CentOSに最初からインストールされているのはGNU AWKですが、Ubuntuではmawkです。

  1. $ awk -W version
  2. mawk 1.3.4 20200120
  3. (後略)

バージョン確認時にどのAWKを使用しているのかもセットで押さえておきましょう。

種類によってはオプションが異なる場合があるので、参照した記事のAWKコマンドを実行するとエラーになることがあります。

AWKの基本コマンド

いよいよAWKコマンドを使用した文字列処理・テキストファイル加工に取り掛かりましょう。

サンプルとなるファイルは以下のsample.txtです。

  1. A1 A2 A3 A4 A5
  2. B1 B2 B3 B4 B5
  3. C1 C2 C3 C4 C5

AWKの基本的なコマンド構造は以下のようになっています。

  • $ awk <オプション> ‘<コマンド>’ <入力ファイルパス>

本項ではコマンドについて、次項ではオプションについて詳しく見ていきましょう。

ファイルの内容を検索・出力する

入力ファイルパスにはsample.txtを指定します。

  • $ awk ‘<コマンド>’ sample.txt
ファイルの内容を出力するコマンドは「print」です。

  1. $ awk ‘{ print }’ sample.txt
  2. A1 A2 A3 A4 A5
  3. B1 B2 B3 B4 B5
  4. C1 C2 C3 C4 C5

類似のコマンドに「printf」がありますが、こちらは行末ごとに自動で改行されることがありません。

  1. $ awk ‘{ printf “%s-%s-%s”, $1, $3, $5 }’ sample.txt
  2. A1-A3-A5B1-B3-B5C1-C3-C5–$
  3. $ awk ‘{ printf “%s-%s-%s\n”, $1, $3, $5 }’ sample.txt
  4. A1-A3-A5
  5. B1-B3-B5
  6. C1-C3-C5

またファイルの一部のみを出力したい場合は、以下のように「$<列番号>」を指定します。

  1. $ awk ‘{ print $3, $5 }’ sample.txt
  2. A3 A5
  3. B3 B5
  4. C3 C5

行を指定するときは「NR==<行番号>」をセミコロンで区切り並べるだけです。

  1. $ awk ‘NR==1;NR==3’ sample.txt
  2. A1 A2 A3 A4 A5
  3. C1 C2 C3 C4 C5

特定の文字列を含む行を取得する場合は「/<文字列>/」というコマンドになります。

  1. $ awk ‘/C4/’ sample.txt
  2. C1 C2 C3 C4 C5

AWKの変数を使う

では「'{ print $NR }’」と指定したら、どのような出力結果になるでしょうか。

  1. $ awk ‘{ print $NR }’ sample.txt
  2. A1
  3. B2
  4. C3

実はNRはAWKの変数で現在処理しているレコードの番号を表します。

つまり上記コマンドではA行$1・B行$2・C行$3となり、行番号と同じ列番号の値が出力されるという訳です。

変数にはファイル名を出力するFILENAME、処理しているフィールド数を表すNFなどがあります。

AWKの関数を利用する

コマンド中でAWKの組み込み関数を使用する方法です。

特定の文字列を置換するsub関数・gsub関数を使うと、条件に当てはまる文字列に処理を行うことができます。

  1. $ awk ‘{ sub(“B”, “BX”); print }’ sample.txt
  2. A1 A2 A3 A4 A5
  3. BX1 B2 B3 B4 B5
  4. C1 C2 C3 C4 C5
  5. $ awk ‘{ gsub(“B”, “BX”); print }’ sample.txt
  6. A1 A2 A3 A4 A5
  7. BX1 BX2 BX3 BX4 BX5
  8. C1 C2 C3 C4 C5

sub関数は最初に見つけた1フィールドのみを置換し、gsub関数は見つけた全てのフィールドを置換する関数です。

AWKのパターン処理

前項の出力結果をB行のみにしたい場合はどうすれば良いでしょうか。

本項ではパターンの指定方法について説明します。

コマンドの中身は「<パターン>{<アクション>}」に分解可能です。

例えばBが含まれる行のみを処理対象としたい場合の指定は以下のようになります。

  1. $ awk ‘/B/{ sub(“B”, “BX”); print }’ sample.txt
  2. BX1 B2 B3 B4 B5
  3. $ awk ‘/B/{ gsub(“B”, “BX”); print }’ sample.txt
  4. BX1 BX2 BX3 BX4 BX5

今までのコマンドでは主にパターンを指定していなかったため、処理対象となるデータが全ての行になっていただけです。

また「/C4/」はパターンのみを指定した例であり、このときの<コマンド>のデフォルトは「{ print }」と同じになります。

AWKの主要オプション


今度は以下のsample.csvファイルを想定してみましょう。

  1. W1,W2,W3
  2. X1,X2,X3
  3. Y1,Y2,Y3
  4. Z1,Z2,Z3

区切り文字を指定する

以下のコマンドを実行すると空行のみが出力されます。

  1. $ awk ‘{ print $2 }’ sample.csv

AWKは何も指定しなければ空白を区切り文字とするので、行頭から行末までを$1として処理している状態です。

-Fオプションで区切り文字を指定して、正しく認識させましょう。

  1. $ awk -F “,” ‘{ print $2 }’ sample.csv
  2. W2
  3. X2
  4. Y2
  5. Z2

変数を定義する

コマンドライン上で変数を定義し、コマンドに渡すことができるオプションです。

  1. $ awk -v hoge=”H” -v fuga=”F” ‘BEGIN{ print hoge fuga }’ sample.csv
  2. HF

AWKスクリプトを実行する

script.awkという名前のファイルを新規作成し、以下のスクリプトを入力して保存して下さい。

AWKスクリプトはコマンドをファイルに切り出したもので、簡単なプログラムから複雑なシステムなど様々な場面で有用です。

  1. #!/usr/local/bin/gawk -f
  2. {
  3.  print $1, $3
  4. }

-fオプションでAWKスクリプトファイル名を指定すると、ファイル内に記述されたスクリプトを実行することができます。

  1. $ awk -f script.awk -F “,” sample.csv
  2. W1 W3
  3. X1 X3
  4. Y1 Y3
  5. Z1 Z3

AWKの制御文

AWKスクリプトを別ファイルとして定義する方法が分かりました。本項ではif文やfor文などの基本的な制御文について説明します。

  1. 2020-05-04 15:30 afternoon snack
  2. 2020-05-05 10:00 morning snack
  3. 2020-05-05 15:00 afternoon snack

if文

if文を使用すれば明示的かつ柔軟に条件を指定し、結果を出力することができるようになるでしょう。

  1. {
  2.   if($1 == “2020-05-05”){
  3.  print $0
  4. }
  5. }

  1.  $ awk -f script.awk sample.log
  2. 2020-05-05 10:00 morning snack
  3. 2020-05-05 15:00 afternoon snack


複数の条件をAND条件で指定するときは「&&」を、OR条件で指定するときは「||」を使用します。

  1. {
  2.   if($1 == “2020-05-05” && $3 ~ /^morning/){
  3.  print $0
  4. }
  5. }

  1.  $ awk -f script.awk sample.log
  2. 2020-05-05 10:00 morning snack

「$<列番号> ~ /<正規表現>/」は対象の列のフィールドが正規表現に当てはまるかどうかを指定する記法です。

while文・for文


while文・for文は条件を満たしている間、同じ処理を繰り返す制御文ですが、ほとんど他の言語と同様のためfor文のみ記載しておきます。

  1. BEGIN{
  2.   for(i = 1; i <= 3; i++){
  3.    sum += i
  4.   }
  5.  print sum
  6. }


  1.  $ awk -f script.awk sample.log
  2. 6

delete文

delete文は指定した要素を削除する制御文です。

  1. BEGIN{
  2.  split(“a b c d” , arr, ” “)
  3.   delete arr[3]
  4.   for(i in arr) {
  5.  print i “-” arr[ i ]
  6.   }
  7. }

  1. $ awk -f script.awk sample.log
  2. 1-a
  3. 2-b
  4. 4-d

AWKの組み込み関数

AWKにはいくつかの有用な組み込み関数が用意されています。

数学関数

数学関係の組み込み関数です。

  • sin関数(サイン・正弦をラジアンで返却)
  • cos関数(コサイン・余弦をラジアンで返却)
  • log関数(自然対数)
  • rand関数(乱数)

文字列関数

sub関数・gsub関数は文字列関数に属します。その他の主要な文字列処理関係の組み込み関数は以下です

  • length関数(文字列の長さ)
  • split関数(文字列の分割)
  • tolower関数・toupper関数(大文字小文字変換)
  • match関数(正規表現検索)

AWKのユーザー定義関数

ユーザーが独自関数を定義できるようになっています。

例えばdelete文の項で使用した配列の内容を出力する部分を、ユーザー独自関数として切り出してみましょう。

ユーザー定義関数の記法は「function 関数名(引数, 引数, …){ <コマンド> }」です。

  1. function printarr(arr) {
  2.  print “—–“
  3.  for(i in arr) {
  4.  print i “-” arr[ i ]
  5.   }
  6. }
  7. BEGIN{
  8.  split(“a b c d” , arr, ” “)
  9.   printarr(arr)
  10. delete arr[3]
  11.  printarr(arr)
  12. }

このscript.awkを実行した結果は以下のようになります。

  1. $ awk -f script.awk sample.log
  2. —–
  3. 1-a
  4. 2-b
  5. 3-c
  6. 4-d
  7. —–
  8. 1-a
  9. 2-b
  10. 4-d

おわりに

AWKを使いこなせるようになるとCSVファイルの操作やログ解析を効率的に実行可能です。

コマンドラインが苦手な方にはハードルが高いかもしれませんが、AWKを使いこなせればサーバー情報取得の強い味方になります。

AWK以外にもLinux系ディストリビューションで使用できる、デフォルトでインストールされている言語は使えるようにしておくと良いでしょう。

toiroフリーランスは、SHIFTグループがプライムとして参画している独自案件をフリーランスエンジニア向けに紹介する唯一のプラットフォームサービスです。

エージェントによるサポートもありますので、ご利用を検討してみてはいかがでしょうか。