awkの連想配列(アクセスログを例に)

こんにちは。hacknoteのj.kushiyamaです。 今回学習したことの一部としてawkの連想配列についてアクセスログを例にとって解説したいと思います。

アクセスログの例

以下のようなアクセスログを考えます。

...
x.x.x.x - - [17/Apr/2015:03:25:26 +0900] "GET /archives/8009 HTTP/1.1" 200 11971 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
x.x.x.x - - [17/Apr/2015:03:25:26 +0900] "GET /archives/63829 HTTP/1.1" 200 13040 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
x.x.x.x - - [17/Apr/2015:03:25:29 +0900] "GET /wp-content/upload/ HTTP/1.1" 304 - "-" "Googlebot-Image/1.0"
...

例1)アクセスログからアクセスの多いIPアドレスと回数を降順に並べ替える

この場合のスクリプトは以下のようになります。

#!/bin/bash                                                                                                                                                                                                                  
cat access-log |awk 'BEGIN{FS="-"}{num[$1]++}END{for(i in num){print num[i] ":" i}}' | sort -r -n

FSはフィールドセパレータといい、ファイル内の区切り文字のことを表します。ここでは”-“をフィールドセパレータとしています。これはアクセスログファイルの形式によって異なるので、最初の部分を実際に見て適宜変更してみてください。csvファイルなら”,”を指定すると良いでしょう。


awkでは

BEGIN{...}END

の…の文章の処理が繰り返し行われます。 $1をフィールドといい、(-を区切り文字とした)列に相当します。

num[$1]++

で、ある$1の出現回数を取得できます。これを連想配列といいます。

例えば、

num[x.x.x.x]++

で(x.x.x.xはIPアドレス)の出現回数を一回増やすことができます。
END内の操作が最後に行われます。添字iがIPアドレスそのものに相当し、num[i]はiの出現回数を表します。

sort -r -n で回数についての降順に並べ替えることができます。

例2)アクセスログからアクセスの多いユーザーエージェントを降順に並び替える

  #!/bin/bash
  cat access-log |awk  -F\" '{num[$6]++}END{for(i in num){print num[i] ":" i}}' | sort -r -n

これは例1と同様に考えれば、$6にユーザーエージェントが記載されていると読み取れます。(ユーザーエージェントの記載されたフィールドはアクセスログの記法によって異なります)

awkの-Fオプションで区切り文字を指定することもできます。この場合では”をエスケープして指定していて、これをフィールドセパレータとしたときに上の例では6番目のフィールドにユーザーエージェントが記載されているとわかります。あとは例1と同様です。