SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

USP MAGAZINEコラボレーション連載/「シェル芸」に効く AWK処方箋

AWKプログラミングの真髄の1つ
フィールド(列)を操る基礎テクニック

► 「シェル芸」に効く AWK処方箋 第3回 (月刊『USP MAGAZINE 2014 June (Vol.14)』より転載)


  • このエントリーをはてなブックマークに追加

 前回はAWKのレコード、すなわち行について学びました。今回はフィールド、つまり列について説明します。列を抜き出すのに、cutコマンド編注1の代わりにAWKを利用するケースを見かけますが、AWKのフィールド操作は、cutコマンドよりもはるかに強力なものになっています。そこで、今回もシェル芸編注2でよく使われる事例を中心に説明していきます。

  • このエントリーをはてなブックマークに追加

編注1:指定された区切り文字で項目を分割するコマンド。
編注2:「シェル芸」とは、UNIXシェル(主にbash)のワンライナーを駆使して文字列加工を自由自在に操ることです。また、そのような能力をもつ人をシェル芸人と呼びます。

 

フィールドとは?

 AWKは読み込んだテキストファイルをレコード(デフォルトでは行に相当)に自動的に分割しますが、さらにそのレコードをフィールドというものに分割します。このフィールドはデフォルトでは英文の単語に該当します。具体的には、1つのレコードの中を組込変数FS(Field Separator)で分割したものをフィールドと言います

 このフィールドはレコードの先頭から$1、$2、$3……と分割されていきます。さらに、現在処理中のレコードでのフィールド数は組込変数NF(Number of Filed)で定義されますので、レコードの末尾からは$NF、$(NF - 1)、$(NF - 2) ……と定義されます。シェルの引数と似ているため、混同しないように注意しましょう。

 例えば、"This is a pen." という英文があったとすると、次のように分割されます。

This         is           a            pen.
$1           $2           $3           $4
$(NF - 3)    $(NF - 2)    $(NF - 1)    $NF

 これは、デフォルトで組込変数FSが連続するスペースまたはタブになっているため、英文のようにスペースで区切られたものを処理する場合には都合の良いものになっています。また、多くのUnix系OS上で動作するサービスのログファイルの構造は、AWKでも処理しやすいように、ほとんどのものがスペースやタブで区切られています。

 よく利用するテキストファイルの代表として、カンマ(,)でデータが区切られたCSVファイルがありますが、組込変数FSにカンマ(,)を代入することで、CSVファイルを扱うことができます。

$ echo "a,b,c" | awk -F',' '{print $2}'
b

 AWKでは組込変数FSがしばしば変更されるためか、他の変数は-vオプションで指定するのに対し、組込変数FSだけは-Fオプションで直接指定できるようになっています。

 ただし、CSVファイルのフォーマットには、データをダブルクォート(")で括るようなものや、改行を含むようなものもあります。そのような場合には、標準的なAWKではどちらも扱うことができません。GNU AWK(gawk)編注3であれば前者に限り新しく定義された組込変数FPATを定義することで対応できますが、ここでは割愛します。

編注3:GNUプロジェクトで開発されているAWK。オリジナルのAWKにない機能が追加されている。

 少し不思議な例を挙げておきます。AWKの組込変数FSは、連続するスペースまたはタブであると書きました。では、正規表現で記述した際には、[ \t]+ と同義なのでしょうか? 実は違います。記事の文面からは分かりづらいかもしれませんが、先頭にスペースを含めたもので試すと分かります。

$ echo "    a b c" | awk '{print $2}'
b
$ echo "    a b c" | awk -F'[ \t]+' '{print $2}'
a

 では、組込変数FSのデフォルトは何なのでしょうか。実は、スペース1つで定義されています。

$ echo "    a b c" | awk -F' ' '{print $2}'
b

 様々なファイルを読み込むような場合だと、組込変数FSを変更していくことがあります。ふたたびデフォルトに戻したいこともありますが、そのような場合に覚えておくと同時に、自分で組込変数FS を設定した場合には行頭がどうなるかを注意しましょう。

指定フィールドを抜き出す

 AWKによるフィールド操作で最もよく使われるものが、特定のフィールドの抜き出しではないでしょうか。すでに何度か例として挙げていますが、単純にprint文の引数としてフィールドを指定するだけです。

$ echo "a b c" | awk '{print $2}'

 もちろん、本連載の第1回で説明したように、$0に抜き出したいフィールドを指定するだけでも同じことができます。

$ echo "a b c" | awk '$0 = $2'

 これは、レコード($0)に第2フィールドを代入することを意味しますが、AWKでは代入に成功します。代入の真偽は左辺値で決まりますので、代入された$0が数字の0(ゼロ)または空文字列でない限り、真になります。真の場合には {print $0} が省略されたものとみなされるため、結果として$2が代入された$0が表示されることになります。

 もちろん、抜き出したいものが数字の0や空文字列である場合には偽になってしまうため、何も表示されません。

$ echo "0 1 2" | awk '$0 = $1'
  ←何も表示されない
$ echo "0 1 2" | awk '{print $1}'
0

 これは、cutコマンドでも同様のことができます。

$ echo "0 1 2" | cut -d' ' -f1
0

 AWKのフィールドの抜き出しとcutコマンドの最大の違いは、フィールドの区切りに正規表現が使えるかどうかという点でしょう。前回、組込変数RSには正規表現が使えない(gawkを除く)と書きましたが、組込変数FSには正規表現を用いることができます。したがって、以下に例として挙げた日付や時刻の区切りであるスペースやコロン、スラッシュを、まとめて組込変数FSに指定することができます。

$ echo "2014/03/08 12:12:12" | \\
  awk -F'[ :/]' '{print $2}'
03

 

指定フィールドを消す

 指定したフィールドのみを削除するには、指定したフィールドに空文字列を代入します。

$ echo "a b c" | awk '{$2 = ""; print}'
a  c

 その後の処理にも依存しますが、上記のaとcの間にはスペースが2つ入ってしまっていますので、注意が必要です。

 これをパターンのみで記述すると次のようになることは、本連載の第1回でも説明しました。

$ echo "a b c" | awk '!($2 = "")'
a  c

 また、フィールド数が少ない場合には、特定のフィールドを削除するよりも、消したいフィールド以外を表示したほうが、簡単で分かりやすいと思います。

$ echo "a b c" | awk '{print $1, $3}'
a c

 実は、このprint文で用いたカンマは特殊で、組込変数OFS(Output Field Separator)に置き換えられます。組込変数OFSはデフォルトではスペース1つです。

 AWKにはフォーマットを指定して表示することができるprintf文もありますので、以下のようにしても同じ結果が得られます。

$ echo "a b c" | awk '{printf("%s %s\\n", $1, $3)}'
a c

 注意していただきたいのは、このprintf文のカンマは引数の区切りであり、組込変数OFSを示すものではないことです。カンマを組込変数OFSとして扱うのは、print文だけです。

 AWKには、print文とprintf文の両方の出力方法が用意されていますので、ある程度長いプログラムを作成する際には統一したほうが良いでしょう。

本連載が単行本になりました!

「シェル芸」に効く!AWK処方箋

Amazon  その他

「シェル芸」に効く!AWK処方箋

著者:斉藤博文
発売日:2017年1月31日(火)
価格(POD):2,160円(税込)
価格(電子書籍):1,728円(税込)

本書について

 コマンドであり軽量言語(LL)の元祖でもあって、シェルでのテキストデータ処理には便利で手放せない「AWK」の魅力と書き方、シェルコマンドと組み合わせたテクニック(シェル芸)を解説。
 プリントオンデマンド(POD)と電子書籍にて、絶賛発売中です!

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
範囲指定でフィールドを抜き出す

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
USP MAGAZINEコラボレーション連載/「シェル芸」に効く AWK処方箋連載記事一覧

もっと読む

この記事の著者

斉藤 博文(サイトウヒロフミ)

最初にAWKと出会ってから○十年、AWKの魅力に取りつかれ、勢い余って「日本 GNU AWKユーザー会」を立ち上げています。会としてOSCなどのイベントにも出展しつつ、GNU AWKの開発も手伝っています。「USP友の会」では幹事役ですが、「シェル芸勉強会」にはほぼ毎回参加して一緒に勉強しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7852 2017/01/31 20:02

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング