前回はフィルタコマンド「awk」の配列とfor制御構文について取り上げた。今回は、while制御構文について説明しよう。

while制御構文

前回紹介したawkスクリプトのなかでは、2つの処理でfor制御構文を使っていた。1つは、都道府県ごとに数を積算する処理だ。


for (j=1; j<=48; j++)
      if ($2==n[j])
         t[j] += 1

もう1つは、都道府県ごとに積算数を出力する処理(0件の場合は出力しない)である。


for (j=1; j<=48; j++)
     if (0 != t[j])
         printf("%s  \t%d件\n",n[j],t[j])

これらをwhile制御構文で書き換えると、それぞれ次のようになる。


j=1
      while (j<=48) {
         if ($2==n[j])
             t[j] += 1
         ++j
      }

j=1
      while (j<=48) {
         if (0 != t[j])
             printf("%s  \t%d件\n",n[j],t[j])
         ++j
      }

for制御構文もwhile制御構文も、書き方が少し違うだけで内容はほとんど同じだ。forやwhileといった制御構文を持つプログラミング言語は多いので、プログラマーならばよく見かけるコードだろう。

while制御構文に書き換えた場合、前回のawkスクリプトは次のようになる。


#!/bin/sh

key="$1"
awk '
BEGIN {
      ken = "愛知県 青森県 秋田県 石川県 茨城県 岩手県 愛媛県 " \
      "大分県 大阪府 岡山県 沖縄県 香川県 鹿児島県 神奈川県 岐阜県 " \
      "京都府 熊本県 群馬県 高知県 埼玉県 佐賀県 滋賀県 静岡県 " \
      "島根県 千葉県 東京都 徳島県 栃木県 鳥取県 富山県 長崎県 " \
      "長野県 奈良県 新潟県 兵庫県 広島県 福井県 福岡県 福島県 " \
      "北海道 三重県 宮城県 宮崎県 山形県 山口県 山梨県 和歌山県"
      split(ken, n);

      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)
      j=1
      while (j<=48) {
            if ($2==n[j])
                  t[j] += 1
            ++j
      }
}

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

当然ながら、実行結果は前回と同じになる。特に難しいことはないと思うが、インデックスの開始が0ではなく1になることに留意しておいてほしい。

while制御構文とよく似たものに、do while制御構文がある。この構文では、最初に繰り返しの中身を実行し、最後に式を評価する。今回、while制御構文に書き換えた部分をさらにdo while制御構文に書き換えると次のようになる。


j=1
      do {
            if ($2==n[j])
                  t[j] += 1
            ++j
      }
      while (j<=48)

j=1
      do {
            if (0 != t[j])
                  printf("%s  \t%d件\n",n[j],t[j])
            ++j
      }
      while (j<=48)

当然ながら、書き換えても実行結果は同じだ。

それ以外の制御構文としては、繰り返し構文から抜ける「break」と「continue」、処理を終了する「exit」、次のレコードに移る「next」などがある。この辺りを押さえておけば、awkのスクリプトは大体読めるようになるのではないかと思う。

自分で書く分には好きな制御構文だけ使っていればよいが、業務上、他人の書いたスクリプトを読まなければならないこともある。こうした記述方法があることは、覚えておくとよいだろう。

今回紹介したスクリプトからもわかるように、これまで取り上げてきた「grep」や「sed」などと比べると、awkのスクリプトにはかなりプログラミング言語感が強い。Linuxサーバの管理者にとって、スクリプトの中身に詳しくなることは必須ではないが、知っておくと何かと便利なはずだ。