SHOEISHA iD

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

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

シェルスクリプトマガジン コラボレーション連載/「シェル芸」に効く GNU AWK処方箋

GNU AWKでCSVファイルを楽々あつかう組込変数FPATと、関数のインダイレクト呼び出し

► 「シェル芸」に効く GNU AWK処方箋 第3回 (月刊『シェルスクリプトマガジン 2014年12月号(Vol.20)』より転載)


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

 AWKはレコードセパレーター(RS)に従いレコードを分割し、フィールドセパレーター(FS)に従いフィールドに分割する言語ですが、この手法ではCSVファイルでフィールド内にカンマを含むような場合に処理を行うことが困難でした。そこでGNU AWKでは新たに組込変数FPAT(フィールドパターン)というものを導入することで簡単に扱えるようになりました。今回はこの組込変数FPATを中心に解説していきます。

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

組込変数FPATの導入

 通常、AWKのフィールド分割は組込変数FSにより分割を行います。この思想はとても便利で、一般的なファイルを処理するのには十分でした。ところが次に示すとおり、CSVファイルをうまく扱えません。

$ echo 'aaa,"bbb,ccc",ddd' |\
> awk -F, '{print $2}'
"bbb

 CSVファイルには「フィールド内にカンマを含む場合にはフィールドをダブルクォートで括る」というルールがありますので、第2フィールドは"bbb,ccc"になるはずですが、うまく取得できていません。こうしたCSVファイルも簡単に扱えるようにする仕組みとして導入されたのが、組込変数FPAT(フィールドパターン)です。

 組込変数FPATを用いると、フィールド内にカンマが含まれている場合でも、次のようにきれいに扱うことができます。

$ echo 'aaa,"bbb,ccc",ddd' |\
> gawk -v FPAT='([^,]+)|(\"[^\"]+\")' '{print $2}'
"bbb,ccc"

 FPAT([^,]+)|(\"[^\"]+\")FPAT,"CSV

 CSV
$ echo -e "aaa,\"bbb\nccc\",ddd" |\
> gawk -v FPAT='([^,]+)|(\"[^\"]+\")' '{print $2}'
"bbb
ddd

 CSVgawk9CSV稿便

 ApacheUser-AgentApache/var/log/httpd/access_logUser-Agent
$ sudo tail -f /var/log/httpd/access_log |\
> gawk -v FPAT='([^ ]+)|(\"[^\"]+\")' '{print $NF}
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"'

 FPAT使patsplit()patsplit()AWKsplit()patsplit()
$ echo 'aaa,"bbb,ccc",ddd' |\
> gawk '{patsplit($0,arr,"([^,]+)|(\"[^\"]+\")"); print arr[2]}'
"bbb,ccc"

 これにより、従来のAWKで扱いづらかったデータにも対応できるようになります。

 

多次元配列

 従来のAWKも、疑似的に多次元配列を持つことはできました。この際はカンマが8進数表記で\034の文字列となり、配列のインデックスが連接として扱われるということは、本連載の前シリーズ「AWK処方箋」の最終回で説明しました。

$ awk 'BEGIN{arr[1, 2]="aaa";print arr[1, 2]}'
aaa

$ awk 'BEGIN{arr[1, 2]="aaa";print arr[1"\034"2]}'
aaa

 こうした疑似的な多次元配列でも十分便利でしたが、gawkでは正式な多次元配列(実際には連想配列なので、正しくは多次元連想配列)が導入されました。

$ gawk 'BEGIN{arr[1][2] = "aaa"; print arr[1][2]}'
aaa

 ただし、この多次元配列は従来の疑似多次元配列とは異なります。

$ gawk 'BEGIN{arr[1][2] = "aaa"; print arr[1, 2]}'
(改行だけが表示される)

 forisarray1.awk
BEGIN {
    arr[1][1] = 300;
    arr[2]["Apple"] = 500;
    arr[3][1, 2] = 700;

    for (i in arr) {
        for (j in arr[i]) {
            print i, j, arr[i][j];
        }
    }
}

 実行してみます。

$ gawk -f isarray1.awk
1 1 300
2 Apple 500
3 12 700

 arrisarray()isarray()
BEGIN {
    arr[1][1] = 300;
    arr[2]["Apple"] = 500;
    arr[3][1, 2] = 700;

    for (i in arr) {
        if (isarray(arr[i])) {
            for (j in arr[i]) {
                print i, j, arr[i][j];
            }
        }
    }
}

 この多次元配列は便利なのですが、次のような場合に気をつける必要があります。

$ gawk 'BEGIN {split("a b c", arr[1]); print arr[1][1]}'
gawk: cmd. line:1: fatal: split: second argument is not an array

 エラーになりましたが、こういう場合には最初にarr[1][1]を空として生成しておく必要があります。

$ gawk 'BEGIN {arr[1][1] = "";split("a b c", arr[1]); print arr[1][1]}'
a

 今までのAWKに慣れてきた人には使いにくいかもしれませんが、行列計算や集計を行う際には便利でしょう。

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

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

Amazon  その他

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

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

本書について

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

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

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

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

メールバックナンバー

次のページ
BEGINFILEとENDFILE

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

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

もっと読む

この記事の著者

 

AWKAWK GNU AWKOSCGNU AWKUSP

稿


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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)

https://codezine.jp/article/detail/8323 2017/01/31 20:07

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング