Linuxのawkコマンドでテキストの加工とパターン処理を行う方法!基本的な使い方とオプションを解説!
数あるLinuxのコマンドの中でも、テキストファイルを自在に加工できる使い勝手のいいコマンドが、sedとgrep、そしてawkです。本記事では、コマンドラインから簡単にさまざまなテキスト処理ができる、Linuxのawkコマンドについて説明します。
目次
Linux awkはどんな事ができるコマンド?
最近ではただLinuxを使うだけであれば、GUIのおかげでほとんどコマンドに当たらずともさまざまな処理が可能となっています。しかし、Linuxをシェル上のワンラインで扱うのであれば、awkはテキストのパターン処理を実行させるために手放すことのできないコマンドとなります。
awkコマンドとは?
awkコマンドは、スペースやカンマで区切られた、表型のテキストの加工処理が得意なコマンドです。現在ではExcelなどの表計算ソフトのお陰で、こうした表型のテキストから適当なデータを見つけたり並べ替えたりするのも簡単になりましたが、awkコマンドはこれをLinuxのターミナル画面で実行させられるコマンドです。
こう説明すると、ExcelやLibreOfficeのCalcを使えばいいのではないか、という意見も出てきますが、アプリを立ち上げてファイルを読み込みその上でデータを処理してそれを書き出す、というプロセスを踏むより、シェルのワンラインでテキストファイルを加工し、別ファイルに保存できるawkの軽快さの方が楽な場合は少なくありません。
しかも、パイプ処理をすればわざわざファイルに書き出す必要もなく、ほかのコマンドの出力結果をすぐにawkで加工してしまえます。しかもよく使うテキスト加工であれば、そのままシェルスクリプトにまとめることも簡単ですし、LinuxのみならずWindowsのMingwやMacにも標準装備されているため、スクリプトをコピーすれば、どこでも利用できます。
awkコマンドの書式とは?
Linuxにおいて、awkはシェル上で以下の書式で実行します。
- awk [オプション] [コマンド] [ファイル]
「オプション」と「コマンド」については、のちほど「Linuxのawkコマンドで使えるオプション」および「Linuxのawkコマンドで使える変数と関数について」の章で説明します。なお、[]内は省略可能です。
Linux awkの基本的な使い方
Linuxでawkが扱うテキストは、主にスペースやカンマなどで区切られた複数行のデータです。それぞれの行のデータをフィールド(列)といい、各行をレコードと呼びます。たとえば上図のlsの出力結果なども、フィールドで構成されたレコードが並んだawkが扱うに便利なデータとなります。まずはこのデータを使って、awkの基本的な使い方を見ていきます。
一部の列のみの値を取り出す
最初にお伝えするのは、awkを使って各行(レコード)から任意の列(フィールド)を取り出す使い方です。awkでは各フィールドは頭から数えた数で示され、n番目のフィールドを$nと記します。したがって、printコマンドを使えば必要な列の値のみを出力できます。
awk '{print $n}'
これを元に、シェル上で先のデータからファイルサイズとファイル名だけを取り出すなら、ファイルサイズは5番目の、ファイル名は9番目のフィールド(列)にありますから、「ls -lh | awk '{print $5,$9}'」でこのふたつのフィールドだけが出力されます。
行全体を表示する
つづいて、フィールド(列)を表示するのではなく、シェル上である文字を含んだレコード(行)のみを出力する使い方をお教えします。Linuxのawkでは、正規表現を使った文字列を「/」で挟むことで、検索文字列として指定できます。したがって、先のデータから「sh」を含むファイル名のレコードのみを出力するなら、
ls -lh | awk '/sh/'
と入力すれば、以下のように出力されます。
同様に数値の比較も可能です。この場合は文字列の代わりにフィールドの数値を比較します。たとえば100KB以上のファイルを出力させるのなら、シェル上に
ls -l | awk '102400<=$5'
と入力することで、以下のように出力されます。
さらに、ファイル名だけを表示したい場合は、前節の「print $n」を併用して、ファイル名である9番目のフィールドだけを表示させるよう、以下のようにします。
ls -lh | awk '/sh/{print $9}'
なお、0番目のフィールド「$0」を指定するとすべてのフィールドが表示されます。そのため、「ls -lh | awk '/sh/{print $0}'」は「ls -lh | awk '/sh/'」と同じ結果を返します。以上の検索文字列と、フィールドを指定したprintコマンドを併用することで、awkを使って自在にデータを加工できます。
処理中の列を取得する
Linuxのawkには、フィールドの位置を指定する「$n」以外にも多くの組み込み変数があります。その中にはフィールド(列)の数をカウントする「NF」という組み込み変数もあります。これを使うと、レコード(行)ごとの列の数を表示させることができます。以下がその入力コマンドと出力例です。
ls -lh | awk '{print NF}'
処理中の行を取得する
awkには、フィールド(列)の数をカウントする「NF」同様、レコード(行)の数を表示させる組み込み変数「NR」もあります。以下がその入力コマンドと出力例です。
$ ls -lh | awk '{print NR, $0}'
Linuxのawkコマンドで使えるオプション
Linuxのawkコマンドの基本的な使い方をお伝えしたところで、次にawkの主なオプションについて簡単に説明します。
テキスト加工に使える主なオプションの使い方
Linuxのawkで覚えるべきオプションは以下の3つです。
オプション | 使い方 |
-f <ファイル名> | あらかじめawkスクリプトが記されているファイルを指定 |
-F <区切り文字> | フィールドの区切り文字を指定 |
-v <変数名=値> | 変数を定義 |
よく使うawkスクリプトは、スクリプトファイルを作成しておき、-fオプションで呼びだすことで複雑なスクリプトも簡単に呼びだせます。-Fオプションについては、次の節で詳しく説明します。
-Fオプションでのパターン処理の使い方
Linuxのawkの-Fオプションは、フィールドの区切り文字を指定するオプションです。デフォルトではスペースですが、タブやカンマ、あるいは任意の文字に変更が可能です。
区切り文字をスペースに指定
英文をはじめとする表音文字は、スペースによる分かち書きが普通です。そのため、awkではデフォルトではスペースが区切り文字に指定されていますが、明示的に指定することも可能です。その場合は、
ls -lh | awk -F " " '{print $5,$9}'
とすることで、-Fオプションなしの場合と同じ結果が得られます。
区切り文字をタブに指定
表計算アプリでは、テキスト形式でデータを読み書きする際、タブ区切りデータかカンマ区切りデータが使われます。タブ区切りデータはTSV(tab-separated values)とも呼ばれますが、ExcelではCSV(character-separated values)データとして拡張子.csvが使われます。このタブ区切りデータを使う場合には「-F "\t"」オプションを使います。
区切り文字をカンマに指定
カンマ区切りデータもテキスト形式のデータのやり取りではよく使われる形式です。カンマ区切りということでCSV(comma-separated values)データとも呼ばれ、多くの場合拡張子.csvで扱われます。このカンマ区切りデータを扱う場合は「-F ","」オプションを使います。
区切り文字を複数指定
データによっては統一が取れておらず、タブ区切りとカンマ区切りが混在していたり、セミコロンなど別な区切り文字が使われていたりします。その場合でも、awkなら区切り文字を「-F "[区切り文字A区切り文字B]"」と正規表現で並べて記せば対応できます。タブとセミコロンが混在しているならば、オプションを「-F "[\t;]"」と記せばOKです。
Linuxのawkコマンドで使える変数と関数について
前章ではLinuxのawkのオプションについてお伝えしましたが、この章では変数と関数について簡単にお伝えします。
パターン処理に使える変数と関数の一覧
Linuxのawkでスクリプト処理に使える変数と関数をそれぞれ一覧で記します。これらを組み合わせることで、元のデータを入れ替えたり、違う文字列に変更したり、テキストを自由自在に加工できるようになります。
組み込み変数
変数名 | 意味 |
---|---|
ARGC | 引数の個数 |
ARGV | 配列型の引数 |
ENVIRON | 環境変数を収めた変数 |
FILENAME | 現在処理中のファイルの名前 |
FNR | File's NR。現在処理しているファイルのNR(レコード数) |
FS | Field Separator。フィールドの区切り文字(デフォルトはスペース) |
NF | Number of Fields。処理中のレコードのフィールド数 |
NR | Number of Records。現在処理しているレコード数 |
OFS | Output FS。出力用FS(デフォルトはスペース) |
ORS | Output RS。出力用RS(デフォルトは改行) |
RS | Record Separator。レコードの区切り文字(デフォルトは改行) |
文字列操作用の関数
関数名 | 意味 |
---|---|
gsub(r, s, [t]) | 文字列rを文字列sに置換して、置き換え回数を返す。文字列tを省略した場合は、レコード全体($0)が使用される |
index(s, t) | 文字列s内の文字列tの位置を返す。tが見つからない場合は0を返す |
length([s]) | 文字列sの長さを返す。文字列sを省略した場合は、レコード全体($0)が使用される |
match(s, r) | 文字列s内の文字列rの位置を返し、内部変数RSTARTに開始位置、RLENGTHに文字列の長さをセットする。rが見つからない場合はRSTARTに0、RLENGTHに-1を返す |
split(s, a, [r]) | 文字列rで文字列sを分割し、配列aに格納する。文字列rを省略した場合は組み込み変数FSの区切り文字を使用する |
sprintf(フォーマット指定, 変数リスト) | printfと同様、フォーマット指定に従い整形した文字列を、出力せずに返す |
sub(r, s, [t]) | gsub同様、文字列rを文字列sに置換するが、最初のものだけで終了する。文字列tを省略した場合は、レコード全体($0)が使用される |
substr(s, i, [n]) | 文字列s中のi文字目からn文字を返す。nを省略した場合はi文字目から最後の文字までを返す |
tolower(s) | 文字列s内の大文字をすべて小文字に変換して返す |
toupper(s) | 文字列s内の小文字をすべて大文字に変換して返す |
使用例
上記の組み込み変数や関数を使うことで、Linuxのawkではさまざまなスクリプトを作成できます。しかし、そのすべてをお伝えすることはできませんから、ここでは組み込み変数を利用して区切り文字を変更し、テキストを加工する様子を使用例としてお伝えします。
入力テキストの区切り文字を指定する
前章では、-Fオプションを使って区切り文字を指定しました。しかし、組み込み変数の表を見ればわかる通り、組み込み変数FSに新しい区切り文字を入力しても、区切り文字が指定できます。そこで、タイムスタンプに含まれる「:」を区切り文字として、後半部分を表示させるスクリプトを作ってシェル上に入力します。
ls -lh | awk '{FS=":";print $2}'
すると、下図のようにタイムスタンプの分部分とファイル名が2番目のフィールドとして拾われ、それが表示されます。
出力時の区切り文字を指定する
同様に、出力時の区切り文字も組み込み変数OFSで変更可能です。したがって、区切り文字をたとえば「....」に変更するのなら、シェル上のコマンドラインを、
ls -lh | awk '{OFS="....";print}'
とすればすむはずです。しかし、OFSを書き換えるだけでは出力に反映されないため、レコードを一度書き換える必要があります。そこで、$1=$1と同じデータで上書きすることで書き換えを行い、シェル上のコマンドを以下のスクリプトに変更します。
ls -lh | awk '{OFS="...."};NF != 0 {$1 = $1;};{print}'
すると、以下のように区切り文字がピリオド4つに加工されたデータが出力されます。
Linuxのawkコマンドでテキスト加工をやってみよう
以上、Linuxのシェル上でスクリプトを作成して、自由自在にテキストを加工できるawkのごくごく基本的なことについて説明してきました。awkは非常に奥深いコマンドですので、本記事を入り口としてawkを利用し、いずれはawkのスクリプトを極めてください。