Linuxコマンド辞典 awkコマンド(テキスト処理)

テキストのパターンの検知/処理を行う「awk」コマンドの概要と使い方を記載しています。

RHEL Fedora CentOS Vine Deblan Ubuntu Plamo

概要・使用方法

awkは簡易なプログラミング言語で、指定したファイルや標準入力からテキストデータを読み込み、行単位で処理を実施します。テキストデータの1行を、フィールド区切り文字(デリミタ)で分割し、複数のフィールドを作成します。各フィールドは$1,$2、・・・といった変数に格納されアクセスすることができます。多くのディストリビューションでは、GNU版のawkが標準awkとしてインストールされています。

awkスクリプトの基本構成は「条件{処理}」です。条件にマッチした行について処理を行います。「条件」には、検索対象文字列や正規表現による文字列を指定し、「>」や「<」などの条件演算子を利用した関係式で指定します。「処理」には、printなどのawk内部コマンドを利用します。

条件や処理には組み込み変数を利用できます。NR(行数)やFILENAME(ファイル名)、NF(フィールド数)などがあります。各行は空白区切りのフィールドの集まりとします。行全体は「$0」で、各フィールド(列)は「$1」「$2」・・・という変数で取り出すことができます。awkはプログラミング言語の一つですが、各行同じフォーマットのテキストを読み込み、特定の列を出力するのに多用されます。

例としては、Webサーバアクセスログから特定の時刻のアクセスホストを取り出してカウントすることでアクセス数を算出したり、アプリケーションが出力するログを集計し、Zabbixなどのネットワーク管理ソフトウェアに集計値を渡しサービス状態を監視することなどに使われます。

書式

$awk [オプション] [awkスクリプト] [ファイル名・・・]

オプション

-f ファイル名
–file ファイル名
引数ファイルをawkスクリプトとして読み込む
-F 文字
–field-separator 文字
区切り文字列を指定する(デフォルトは空白)
-v 変数=値
–assign 変数=値
スクリプトで利用する変数を設定する。複数の変数が指定可能

主な組み込み変数

組み込み変数説明
$nn番目のフィールド
$0レコード全体
FILENAME入力ファイル名
FSフィールドの区切り文字(デフォルトは空白文字列)
NF入力レコード内のフィールド数
NR処理したレコードの数
RSレコードの区切り文字(デフォルトは改行)

指定したフィールドを指定する

/etc/passwdファイルの内容を1行ずつ:(コロン)で分割し変数に格納します。$1=第1フィールド(ユーザー名)。$3=第3フィールド(UID)、$7=第7フィールド(デフォルトシェル)を抜き出して表示します。

$ awk -F ":" '{ print $1, $3, $7 }' /etc/passwd

実行結果

[root@localhost ~]# awk -F ":" '{ print $1, $3, $7 }' /etc/passwd | more
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
・
・
・
[root@localhost ~]# 

指定したフィールドに条件を付けて表示する

/etc/passwdファイルを:(コロン)で分割し変数に格納します。UID($3=第3フィールド)が1000以上の行を表示します。

$ awk -F":" '$3 >= 1000 { print NR, $0 }' /etc/passwd

実行結果

[root@localhost ~]#  awk -F":" '$3 >= 1000 { print NR, $0 }' /etc/passwd
36 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
43 sunarin:x:1000:1000:sunarin:/home/sunarin:/bin/bash
[root@localhost ~]# 

awkコマンドをファイルに記述し実行する

ls -lの出力からパーミッション、サイズ、ファイル名を表示し、最後にファイルサイズを合計するawkスクリプトを作成して、awkコマンドに渡します。

$ ls -l | tail -n +2 | awk '{print $1,$5,$9} {s+=$5} END {print "Total: " s}'

実行結果

[sunarin@localhost work]$ cat awktest.txt 
{
 print $1,$5,$9
}

{
 s+=$5
} 

END {
 print "Total: " s
}
[sunarin@localhost work]$ ls -l | tail -n +2 | awk -f awktest.txt 
-rw-rw-r-- 51 Country.txt
-rw-rw-r-- 61 awktest.txt
-rw-rw-r-- 146 hostlist1.txt
-rw-rw-r-- 38 hostlist2.txt
-rw-rw-r-- 53 iplist.txt
drwxrwxr-x 38 log
-rw-rw-r-- 146 output.txt
-rw-rw-r-- 129 sample.sh
-rw-rw-r-- 125 sample.sh.bak
-rw-rw-r-- 49 sample.txt
-rw-rw-r-- 65 sed1.sh
Total: 901
[sunarin@localhost work]$ 

awkコマンドスクリプトファイルにしない場合

$ ls -l | tail -n +2 | awk '{print $1,$5,$9} {s+=$5} END {print "Total: " s}'

実行結果

[sunarin@localhost work]$ ls -l | tail -n +2 | awk '{print $1,$5,$9} {s+=$5} END {print "Total: " s}'
-rw-rw-r-- 51 Country.txt
-rw-rw-r-- 146 hostlist1.txt
-rw-rw-r-- 38 hostlist2.txt
-rw-rw-r-- 53 iplist.txt
drwxrwxr-x 38 log
-rw-rw-r-- 146 output.txt
-rw-rw-r-- 129 sample.sh
-rw-rw-r-- 125 sample.sh.bak
-rw-rw-r-- 49 sample.txt
-rw-rw-r-- 65 sed1.sh
Total: 840
[sunarin@localhost work]$ 

文字列を検索して、最初の単語を取り出し並べ替え、重複行を削除、行数をカウントする

apacheのアクセスカウントに使用することができます。以下の例はApacheのアクセスログから5月1日アクセスログの行を抽出し、awkでホスト名(先頭)だけ抜き出します。抜き出したホスト名をsortコマンドでソートして、uniqコマンドで重複行を取り除きます。wcコマンドでカウントします。

$ grep 01/May /var/log/httpd/access_log | awk '{ print $1 }' | sort | uniq | wc -l