本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。
本連載では、Linuxの基本的なコマンドについて、基本的な書式からオプション、具体的な実行例までを分かりやすく紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。連載第115回、第116回に続き、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 [オプション] [コマンド] [ファイル……]
※[ ]は省略可能な引数を示しています
短いオプション | 意味 |
---|---|
-f ファイル名 | awkスクリプトが書かれたファイルを指定する |
-F 区切り文字 | 区切り文字を指定する(デフォルトは空白文字) |
-v 変数名=値 | 変数を定義する |
※gawk(GNU版awk)の場合、長いオプションも使用可能。-fは--file program-file、-Fは--field-separator、-vは--assign。gawkにはこの他にも多数のオプションがある。
変数名 | 意味 |
---|---|
ARGC | 引数の個数 |
ARGV | 引数(配列) |
ENVIRON | 環境変数を収めた連想配列。例えば環境変数LANGならばENVIRON["LANG"]と参照できる |
FILENAME | 現在処理しているファイルの名前 |
FNR | 現在処理しているファイルのレコード番号(処理しているファイルが1つの場合はNRと同じ値になる) |
FS | フィールドの区切り文字(-Fオプションで変更可能、デフォルトはスペース) |
NR | 現在処理しているレコード番号(行番号) |
OFS | 出力時のフィールドの区切り(デフォルトは空白) |
ORS | 出力時のレコードの区切り(デフォルトは改行) |
RS | レコードの区切り(デフォルトは改行) |
awkは「パターン {アクション}」で処理を指定します。パターンに合致したらアクションを実行する、という意味です。
例えば「ls -l | awk '$5 >= 1000000 { print }'」とあれば、「ls -lで、5番目のフィールド(サイズが表示されるフィールド)が100000以上であった場合に出力する」という意味になります(画面1、連載第115回)。
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の内容を行番号付きで出力しています。コマンドラインでの入力を簡略化するために空白を省いています。
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のような書き方が便利です。
例えば、先ほどの「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回も参考にしてください。
西村 めぐみ(にしむら めぐみ)
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.