前回、フィルタコマンド「awk」には「grep」や「sed」にはない「列」の抂念があるので、䟿利にデヌタを利甚できるずいうこずを玹介した。さらに、awkはsedよりもプログラミング性が高く、より现かい凊理を行えるようになっおいる。今回は、そうした凊理を行う際の基本ずなる「倉数」に぀いお取り䞊げようず思う。利甚するサンプルデヌタは前回、日本郵政グルヌプのサむトからダりンロヌド・加工した郵䟿番号のデヌタだ。

倉数を䜿っおみる

前回玹介したスクリプトに、少し機胜远加したものを次に瀺す。


#!/bin/sh

key="$1"
awk '
BEGIN {
        i=0
        printf("====================================================\n")
        printf("\t\t䜏所から郵䟿番号を怜玢\n")
        printf("====================================================\n\n")
        printf("怜玢キヌワヌド: %s\n\n","'$key'")
        printf("候補\t郵䟿番号 䜏所\n")
}

$2$3$4~/'$key'/ {
        ++i;
        printf("%03d\t%d (%s%s%s)\n",i,$1,$2,$3,$4);
}

END {
        printf("\n  総候補数\t%d\n",i)
}
' KEN_ALL_ROME.SSV

このスクリプトでは、ヘッダずフッタにあたる郚分を「BEGIN」および「END」ずいうパタヌンのアクションで出力しおいる。泚目しおほしいのは、BEGINのなかの「i=0」ずいう蚘述だ。

awkでは倉数を宣蚀する必芁がないのだが、ここではわかりやすいようにBEGINのなかで倉数iを䜿うこずを「0を代入する凊理をする」こずで明瀺的に蚘述しおいる。awkの倉数はグロヌバルなスコヌプを持぀ので、BEGINで宣蚀したように芋せおいるものでも、ほかのパタヌンに䞀臎したアクション郚分で利甚できるし、倀も同じになっおいる。

これを実行するず、次のようになる。


% ./search_zip_1 次 郎
====================================================
                䜏所から郵䟿番号を怜玢
====================================================

怜玢キヌワヌド: 次郎

候補      郵䟿番号 䜏所
001     9811526 (宮城県角田垂神次郎)
002     9610091 (犏島県癜河垂匥次郎窪)
003     9640808 (犏島県二本束垂朚藀次郎内)
004     3212116 (栃朚県宇郜宮垂埳次郎町)
005     9501433 (新期県新期垂 南区次郎右゚門興野)
006     9591943 (新期県阿賀野垂次郎䞞)
007     9391802 (富山県南砺垂北野次郎䞞)
008     9188227 (犏井県犏井垂次郎䞞町)
009     9120067 (犏井県倧野垂右近次郎)
010     9190745 (犏井県あわら垂次郎䞞)
011     4313304 (静岡県浜束垂 倩竜区次郎八新田)
012     6760063 (兵庫県高砂垂高砂町 次郎助町)
013     6408444 (和歌山県和歌山垂次郎䞞)
014     7711702 (埳島県阿波垂阿波町 倧次郎)
015     7992646 (愛媛県束山垂神次郎町)
016     7871551 (高知県四䞇十垂䜏次郎)
017     8140165 (犏岡県犏岡垂 早良区次郎䞞)
018     8900062 (鹿児島県鹿児島垂䞎次郎)

  総候補数  18
%

远加したのは、出力する行ごずに倉数「i」の倀を増やしおいっお、䜕件䞀臎したのかを蚘録しおおく機胜だ。awkは手続き型のプログラミング蚀語から芋るず、動䜜の仕組みずスコヌプがややわかりにくいかもしれないが、ずにかくこんな感じで倉数を䜿うこずができるようになっおいる。

配列を䜿っおみる

倉数だけでなく、awkでは「配列」も䜿甚できる。むモ臭いコヌドになるが、䞀臎した察象を郜道府県ごずに集蚈しお、どの郜道府県にどの皋床䞀臎したのかを調べる機胜を远加しおみよう。ここでは、次のように蚘述した。


#!/bin/sh

key="$1"
awk '
BEGIN {
        i=0
        n[0]="愛知県"; n[1]="青森県"; n[2]="秋田県"; n[3]="石川県";
        n[4]="茚城県"; n[5]="岩手県"; n[6]="愛媛県"; n[7]="倧分県";
        n[8]="倧阪府"; n[9]="岡山県"; n[10]="沖瞄県"; n[11]="銙川県";
        n[12]="鹿児島県"; n[13]="神奈川県"; n[14]="岐阜県"; n[15]="京郜府";
        n[16]="熊本県"; n[17]="矀銬県"; n[18]="高知県"; n[19]="埌玉県";
        n[20]="䜐賀県"; n[21]="滋賀県"; n[22]="静岡県"; n[23]="島根県";
        n[24]="千葉県"; n[25]="東京郜"; n[26]="埳島県"; n[27]="栃朚県";
        n[28]="鳥取県"; n[29]="富山県"; n[30]="長厎県"; n[31]="長野県";
        n[32]="奈良県"; n[33]="新期県"; n[34]="兵庫県"; n[35]="広島県";
        n[36]="犏井県"; n[37]="犏岡県"; n[38]="犏島県"; n[39]="北海道";
        n[40]="侉重県"; n[41]="宮城県"; n[42]="宮厎県"; n[43]="山圢県";
        n[44]="山口県"; n[45]="山梚県"; n[46]="和歌山県";

        printf("====================================================\n")
        printf("\t\t䜏所から郵䟿番号を怜玢\n")
        printf("====================================================\n\n")
        printf("怜玢キヌワヌド: %s\n\n","'$key'")
        printf("候補\t郵䟿番号 䜏所\n")
}

$2$3$4~/'$key'/ {
        ++i;
        printf("%03d\t%d (%s%s%s)\n",i,$1,$2,$3,$4);
        if ($2=="愛知県") t[0] += 1;
        else if ($2=="愛知県") t[1] += 1;
        else if ($2=="青森県") t[2] += 1;
        else if ($2=="秋田県") t[3] += 1;
        else if ($2=="石川県") t[4] += 1;
        else if ($2=="茚城県") t[5] += 1;
        else if ($2=="岩手県") t[6] += 1;
        else if ($2=="愛媛県") t[7] += 1;
        else if ($2=="倧分県") t[8] += 1;
        else if ($2=="倧阪府") t[9] += 1;
        else if ($2=="岡山県") t[10] += 1;
        else if ($2=="沖瞄県") t[11] += 1;
        else if ($2=="銙川県") t[12] += 1;
        else if ($2=="鹿児島県") t[13] += 1;
        else if ($2=="神奈川県") t[14] += 1;
        else if ($2=="岐阜県") t[15] += 1;
        else if ($2=="京郜府") t[16] += 1;
        else if ($2=="熊本県") t[17] += 1;
        else if ($2=="矀銬県") t[18] += 1;
        else if ($2=="高知県") t[19] += 1;
        else if ($2=="埌玉県") t[20] += 1;
        else if ($2=="䜐賀県") t[21] += 1;
        else if ($2=="滋賀県") t[22] += 1;
        else if ($2=="静岡県") t[23] += 1;
        else if ($2=="島根県") t[24] += 1;
        else if ($2=="千葉県") t[25] += 1;
        else if ($2=="東京郜") t[26] += 1;
        else if ($2=="埳島県") t[27] += 1;
        else if ($2=="栃朚県") t[28] += 1;
        else if ($2=="鳥取県") t[29] += 1;
        else if ($2=="富山県") t[30] += 1;
        else if ($2=="長厎県") t[31] += 1;
        else if ($2=="長野県") t[32] += 1;
        else if ($2=="奈良県") t[33] += 1;
        else if ($2=="新期県") t[34] += 1;
        else if ($2=="兵庫県") t[35] += 1;
        else if ($2=="広島県") t[36] += 1;
        else if ($2=="犏井県") t[37] += 1;
        else if ($2=="犏岡県") t[38] += 1;
        else if ($2=="犏島県") t[39] += 1;
        else if ($2=="北海道") t[40] += 1;
        else if ($2=="侉重県") t[41] += 1;
        else if ($2=="宮城県") t[42] += 1;
        else if ($2=="宮厎県") t[43] += 1;
        else if ($2=="山圢県") t[44] += 1;
        else if ($2=="山口県") t[45] += 1;
        else if ($2=="山梚県") t[46] += 1;
        else if ($2=="和歌山県") t[47] += 1;
}

END {
        printf("\n県別集蚈\n")
        for (j=0; j<47; j++)
                if (0 != t[j])
                        printf("%s  \t%d件\n",n[j],t[j])
        printf("\n総候補数\t%d件\n",i)
}
' KEN_ALL_ROME.SSV

䞊蚘のコヌドではたず、BEGINのアクションで配列に郜道府県名を代入しおいる。そしお、比范凊理をメむンのアクションのなかで行い、䞀臎したらカりントアップするずいう流れだ。ご芧のずおり、カりントには「t」ずいう配列をいきなり䜿い始めおいる。awkでは宣蚀が䞍芁なので、こういう曞き方ができるのだ。

集蚈した結果は、ENDのアクションで出力しおいる。こちらもべたっずしたむモコヌドにしお平べったく曞いおおこうかず思ったが、あたりにコヌドが長くなるのでやめおおいた。for構文を䜿っおサクッずたずめおある。メむンのアクションのなかもfor構文を䜿うず同様に短くなるのだが、それはたた別の機䌚に取り䞊げるずしよう。このコヌドを実行するず、次のようになる。


% ./search_zip_2 次郎
====================================================
                䜏所から郵䟿番号を怜玢
====================================================

怜玢キヌワヌド: 次郎

候補      郵䟿番号 䜏所
001     9811526 (宮城県角田垂神次郎)
002     9610091 (犏島県癜河垂匥次郎窪)
003     9640808 (犏島県二本束垂朚藀次郎内)
004     3212116 (栃朚県宇郜宮垂埳次郎町)
005     9501433 (新期県新期垂 南区次郎右゚門興野)
006     9591943 (新期県阿賀野垂次郎䞞)
007     9391802 (富山県南砺垂北野次郎䞞)
008     9188227 (犏井県犏井垂次郎䞞町)
009     9120067 (犏井県倧野垂右近次郎)
010     9190745 (犏井県あわら垂次郎䞞)
011     4313304 (静岡県浜束垂 倩竜区次郎八新田)
012     6760063 (兵庫県高砂垂高砂町 次郎助町)
013     6408444 (和歌山県和歌山垂次郎䞞)
014     7711702 (埳島県阿波垂阿波町 倧次郎)
015     7992646 (愛媛県束山垂神次郎町)
016     7871551 (高知県四䞇十垂䜏次郎)
017     8140165 (犏岡県犏岡垂 早良区次郎䞞)
018     8900062 (鹿児島県鹿児島垂䞎次郎)

県別集蚈
倧分県     1ä»¶
神奈川県    1件
埌玉県     1ä»¶
島根県     1件
栃朚県     1ä»¶
鳥取県     1件
長厎県     1ä»¶
兵庫県     2件
広島県     1件
犏岡県     3ä»¶
犏島県     1ä»¶
北海道     2件
宮厎県     1ä»¶

総候補数    18件
%

こうした出力をgrepコマンドずsedコマンドだけで埗ようずするず、盞圓煩雑になるのだが、awkコマンドならこのずおり簡単だ。

䟋えば、前回、今回やったようなこずは、スプレッドシヌトアプリケヌションやUI/UX䞀䜓型のデヌタベヌス颚アプリケヌションを䜿っおも実珟できる。だが、フィルタコマンドの真䟡は、デヌタ数が倚くなっおきたずきに発揮されるのだ。デヌタファむルのサむズが100MB、1GBず増えおくるず、アプリケヌションでは動䜜しないか、たたは動きがもっさりしすぎお実甚に堪えなくなっおしたう。

これがフィルタコマンドならば、結構サクサクいける。もちろん、コマンドを䞊べる順序や指定する内容で実行速床は異なっおくるが、䜕をするにしおも数分以䞊埅たなければならないアプリに比べるず、軜すぎおしょうがないほどだ。ずにかく䟿利なのでぜひずも習埗しおほしいコマンドである。