【 awk 】コマンド(応用編その5)――テキストの加工とパターン処理、複数行のレコード処理:Linux基本コマンドTips(211)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、テキストのパターン処理を行う「awk」コマンドです。
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回はテキストのパターン処理を行う「awk(gawk)」コマンドです。
連載第115回、第116回、第117回、第118回、第119回、第120回、第209回、第210回に続き、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オプションで変更可能、デフォルトはスペース) |
NF | 現在処理しているレコードのフィールド数 |
NR | 現在処理しているレコード番号(行番号) |
OFS | 出力時のフィールドの区切り(デフォルトは空白) |
ORS | 出力時のレコードの区切り(デフォルトは改行) |
RS | レコードの区切り(デフォルトは改行) |
awkで使用できる主な文字列操作用の関数
関数(引数) | 意味 |
---|---|
gsub(r, s, t) | 「文字列t」中で「正規表現r」にマッチした箇所全てをsに置き換えて、置き換えた個数を返す。tを指定しなかった場合は「$0」(読み込んだ行全体)が対象 |
index(s, t) | 「文字列s」に含まれる文字列tの位置を返す。tが含まれていない場合は0を返す |
length(s) | 「文字列s」の長さを返す。sを指定しなかった場合には「$0」の長さを返す |
match(s, r) | 「文字列s」で「正規表現r」にマッチする位置を返す。その際、内部変数のRSTARTに開始位置、RLENGTHに長さをセットする。マッチしない場合は0を返す |
split(s, a, r) | 「文字列s」を「正規表現r」で分割し、配列aに格納する。rを省略した時は「FS」(区切り文字、デフォルトは空白)となる |
sprintf(フォーマット指定, 変数リスト) | フォーマット指定に従って整形した文字列を返す。指定方法は「printf」(第118回)と共通 |
sub(r, s, t) | 「文字列t」の中で「正規表現r」へ最初にマッチした箇所をsに置き換える。tを指定しなかった場合は「$0」が対象 |
substr(s, i, n) | 「文字列s」のi文字目からn文字分を返す。nを省略した場合はi文字目以降全てを返す |
tolower(s) | 「文字列s」のうち大文字を全て小文字に変換したものを返す |
toupper(s) | 「文字列s」のうち小文字を全て大文字に変換したものを返す |
※ この他、sin()やlog()、rand()などの数値関数、さらにgawkの場合はsystime()やmktime()などの時間関数を利用できる。
空行区切りのデータを処理する
これまで連載で扱ってきたawk用のデータは、テキストの1行がそのままレコードになっていました。awkは、以下のaddress.txtのようにレコードが複数行にまたがったデータも処理できます。address.txtでは、各レコードが空行で区切られています。
東川 雄一 080-1111-1111 〒111-1111 ××県××区A町 1-1-1 ABCビル1001 西村 祐二 080-2222-2222 〒222-2222 ××県××市B町 2-22 南山 裕三 080-3333-3333 〒333-3333 ××県××市C町 3-3-3 XYZハイツ3号室 北岡 優四 080-4444-4444 〒444-4444 ××県××区D町 4-4-4
このような空行区切りのデータを処理するには、レコードの区切り文字(RS)を「""」に設定します。address.txtでは1つのレコードの中で、氏名や電話番号などが改行で区切られているので、フィールドの区切り文字(FS)は「\n」とします。
画面1では、catコマンド(第1回)でaddress.txtを出力し、awkコマンドで、各ブロックの1行目(氏名の行)と2行目(電話番号)だけを出力しています。
コマンド実行例
cat address.txt | awk 'BEGIN{RS="";FS="\n"}{print $1 $2}'
(レコード区切りを空行、フィールド区切りを改行に設定してデータを処理する)
対象にしたいデータを指定する
1レコードが複数行にまたがっている場合でも、処理の対象にしたいデータを指定する方法は変わりません。通常のパターン指定と同じ方法で進めます(第116回)。
先ほどのaddress.txtで、「××区」が含まれているデータだけを対象としたい場合は、「/××区/{print $1 $2}」のように指定します。
画面2では、次のawkスクリプトをコマンドラインで直接記述しました。
BEGIN{ RS="" FS="\n" } /××区/{ print $1 $2 }
コマンド実行例
cat address.txt | awk 'BEGIN{RS="";FS="\n"}/××区/{print $1 $2}'
(「××区」が含まれるレコードを抜き出す)
空行区切りのデータを集計する
レコードが複数行にまたがったデータを扱う際でも、データの集計をawkコマンドを使って処理できます。
以下のorder.txtは、空行区切りのデータです。各ブロックの1行目が人名、残りが注文と備考データです。注文と備考の行は全てタブで区切られています。注文の行の内容は、品名(A〜D)、単価、個数となっています。
東川 雄一 注文 A 100 10 注文 B 200 5 西村 祐二 注文 B 200 10 南山 裕三 注文 C 300 15 注文 D 400 20 北岡 優四 注文 B 195 5 注文 C 295 15 注文 D 395 20 備考 優待チケットあり
この場合も、先ほど同様、レコードの区切りを空行(RS="")、各レコードのフィールドの区切りを改行(FS="\n")と指定します。注文と備考の行はawkのsplit関数(第210回)を使って分割します。
以下のtotal.awkでは、それぞれのレコードについて、total配列に顧客ごとの金額を集計し、count配列に品物ごとの個数を集計しました。ENDブロックではprintで金額や個数を出力しています。出力を桁ぞろえしたい場合はprintfを使用するとよいでしょう(第118回)。
画面3では処理が長くなったのでスクリプトファイル(total.awk)を使って「awk -f スクリプトファイル データファイル」を実行しています。
BEGIN{ RS="" FS="\n" } { for (i=1;i<=NF;i++){ split($i,d,"\t") #各行(フィールド)をタブ区切りで分割して配列dにセット if (d[1] == "注文"){ #「注文」の場合 total[$1] += d[3]*d[4] #人(各ブロックの1行目)毎の値段を加算 count[d[2]] += d[4] #品物(注文行の2列目)毎の個数を加算 } } } END{ for (i in total){ print i, total[i] } for (i in count){ print i, count[i] } }
コマンド実行例
awk -f スクリプトファイル データファイル
(awkスクリプトファイルを読み込み、データファイルを処理する)
awk -f total.awk order.txt
(total.awkを読み込み、order.txtを処理する)
筆者紹介
西村 めぐみ(にしむら めぐみ)
PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。
Copyright © ITmedia, Inc. All Rights Reserved.