【 awk 】コマンド(基本編その3)――テキストの加工とパターン処理・BEGIN・ENDとAWKスクリプトLinux基本コマンドTips(117)

本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。

» 2017年06月09日 05時00分 公開
[西村めぐみ@IT]
「Linux基本コマンドTips」のインデックス

Linux基本コマンドTips一覧

 本連載では、Linuxの基本的なコマンドについて、基本的な書式からオプション、具体的な実行例までを分かりやすく紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。連載第115回第116回に続き、awkの基本的な使い方を説明します。

awk(オーク)コマンドとは?

 「awk」は空白などで区切られたテキストを処理するコマンドです。演算機能もあり、プログラミング言語としても使用されています。

 Linux環境で使用されているのは、GNUプロジェクトによる「gawk」コマンドが多く、例えばCentOS 7の場合、awkは/usr/bin/gawkへのシンボリックリンクとなっています。

 Ubuntu 15では、Michael D. Brennan氏による「mawk」が収録されています(awkは/etc/alternatives/awkへの、/etc/alternatives/awkは/usr/bin/mawkへのシンボリックリンク)。

 どちらも、もともとのawkに加えてPOSIX 1003.2への準拠や組み込み変数、正規表現指定のバリエーションなどが拡張されています。



awkコマンドの書式

awk [オプション] [コマンド] [ファイル……]

※[ ]は省略可能な引数を示しています





awkの主なオプション

短いオプション 意味
-f ファイル名 awkスクリプトが書かれたファイルを指定する
-F 区切り文字 区切り文字を指定する(デフォルトは空白文字)
-v 変数名=値 変数を定義する

※gawk(GNU版awk)の場合、長いオプションも使用可能。-fは--file program-file、-Fは--field-separator、-vは--assign。gawkにはこの他にも多数のオプションがある。



awkで使用できる主な組み込み変数

変数名 意味
ARGC 引数の個数
ARGV 引数(配列)
ENVIRON 環境変数を収めた連想配列。例えば環境変数LANGならばENVIRON["LANG"]と参照できる
FILENAME 現在処理しているファイルの名前
FNR 現在処理しているファイルのレコード番号(処理しているファイルが1つの場合はNRと同じ値になる)
FS フィールドの区切り文字(-Fオプションで変更可能、デフォルトはスペース)
NR 現在処理しているレコード番号(行番号)
OFS 出力時のフィールドの区切り(デフォルトは空白)
ORS 出力時のレコードの区切り(デフォルトは改行)
RS レコードの区切り(デフォルトは改行)


「BEGIN」は前処理、「END」は後処理

 awkは「パターン {アクション}」で処理を指定します。パターンに合致したらアクションを実行する、という意味です。

 例えば「ls -l | awk '$5 >= 1000000 { print }'」とあれば、「ls -lで、5番目のフィールド(サイズが表示されるフィールド)が100000以上であった場合に出力する」という意味になります(画面1連載第115回)。

画面1 画面1 awkコマンドの基本的な使い方 lsコマンドの出力をawkコマンドで加工した

 1行目より前、つまり処理を開始する前に実行したい処理がある場合は「BEGIN {アクション}」で指定します。

 同様に、最終行まで終えた後に実行したい処理がある場合は「END {アクション}」で指定します。

 例えば、以下のコマンドは、ファイルに行番号を付けて出力し、最後に「(××行)」と処理した行数を出力します。

コマンド実行例

awk 'BEGIN{ i=0 } { print ++i,$0 } END{ print "(" i "行)" }' ファイル名


 ここでは、まず「BEGIN{ i=0 }」で行番号を数えるための変数「i」をゼロに設定しています。

 続く「{ print ++i,$0 }」では、iを1増やして出力し、続いて$0で行全体を出力しています。print部分の書き方は第118回、「++i」のような演算については第119回で取り上げます。

 最後に、「END{ print "(" i "行)" }」で「(××行)」部分を出力しています。

 コマンドラインで実行すると画面2のようになります。ここでは、/etc/shellsの内容を行番号付きで出力しています。コマンドラインでの入力を簡略化するために空白を省いています。

画面2 画面2 awkコマンド実行時にBEGINとENDを指定した例


awk用のファイルを作成する

 awkで処理する内容を書いたファイルを作成しておいて、「awk -f ファイル名」と実行できます。

 コマンドラインで実行する場合のように無理に1行にまとめる必要はありません。例えば先ほどのコマンドラインで書いた内容は、次のようにさまざまな書き方ができます。

 例1は1行にまとめたもの、例2は処理ごとに1行ずつ書いたものです。例3では「{」や「}」と処理内容を分けて書いています。

≪例1≫
BEGIN{ i=0 } { print ++i,$0 } END{ print "(" i "行)" }
≪例2≫
BEGIN{ i=0 }
{ print ++i,$0 }
END{ print "(" i "行)" }
≪例3≫
BEGIN{
  i=0
}
{
  print ++i,$0
}
END{
  print "(" i "行)"
}

 画面3では、例3のスタイルで書いたファイルを実行しています。

画面3 画面3 awk用処理を記述したファイルを指定して実行した例 処理内容は画面2と同じ


アクションの中で複数の処理を行う

 アクション部分、つまり「{」と「}」の間には、複数処理を書くことができます。この場合は例3のような書き方が便利です。

 例えば、先ほどの「print ++i, $0」の部分を、「i=i+1」と「print i, $0」の2つの処理に分けるならば以下のように書きます。#以降はコメントです。

≪例3-2≫
{
  i=i+1          #iを1増やす(++iやi++のように書くことも可能)
  print i,$0
}

 なお、コマンドラインなどで、1行に複数の処理を書きたい場合は「;」で区切ります。例1の書き方の応用です。

awk 'BEGIN{ i=0 } { i=i+1;print i,$0 } END{ print "(" i "行)" }' ファイル名


スクリプトとして実行するには

 awk用のファイルの1行目に「#! /usr/bin/awk -f」と書くことで、「AWKスクリプト」として単独実行できます。

 以下では、先ほどの例3に対し1行目に「#! /usr/bin/awk -f」を追加しています。行番号部分を3桁で出力するように指定しました。printfについては第118回で扱います。

≪例4≫
#! /usr/bin/awk -f
BEGIN{
  i=0
}
{
  printf("%3d %s\n", ++i, $0)
  #行番号部分は3桁で出力。ゼロで埋めたい場合は %3d のようにする
}
END{ 
  printf("(%d行)\n",i)
}

 「chmod」コマンド(第14回)で実行可能属性を付けると、スクリプト名を入力するだけで実行できるようになります(画面4※)

※カレントディレクトリに作成したスクリプトを実行するときの方法については、「"応用力"をつけるためのLinux再入門」第8回も参考にしてください。


画面4 画面4 AWKスクリプトを直接実行した例


筆者紹介

西村 めぐみ(にしむら めぐみ)

PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『はじめてでもわかるSQLとデータ設計』『シェルの基本テクニック』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。