読者です 読者をやめる 読者になる 読者になる

カイワレの大冒険 Third

技術的なことや他愛もないことをたまに書いてます

シェルでループさせて、一部の項目にヒットしたものを集計する方法

プログラミング プログラミング-シェルスクリプト

JSの記事書いたついでなのでかなり適当ですが、更新。アウトプット大事だと思って、たいしたコードじゃないけど、晒します。
基本的に以下のようなことをやりたいのが前提。

  • 繰り返し処理したい。毎回エンターキーとか押したくない
  • gzipで圧縮されてるものから一部切り取りたい
  • でも特定のものは除きたい
  • んで、スマートに集計したい

ということで、for, gzip, fgrep, awkを使い倒すという…

$ for i in 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
> do
> gzip -dc test-$i.gz | fgrep 'php' | fgrep -v 'bflg=1' | awk '!/country/ {i++}END{print i,NR,i/NR}'
> done

カウントするだけなら、パイプで「wc -l」に渡してもいいんだけど、どうせなら集計っぽくしたいので、敢えてawkで。
一応説明。

  • for使って必要なだけループさせるよ!
  • do, doneでそのあいだの処理をするよ!
  • gzipのオプションで、「d」は解凍、「c」は標準出力に吐き出し
  • fgrepでマッチしたものだけ出力するんだけど、「v」つけると、マッチした行は除外されるよ。だから、phpという文字列は含むけど、bflg=1という文字列は含まない行だけを出力するよ
  • 更にawkで正規表現使うよ。countryという文字列にマッチしない行数を変数iにインクリメントしていくよ。NRは全行。割り算とかもできるよ

という感じ。まぁ、ある程度の規模になったら、hbaseとか整形しやすい形をまず作るところから考えたほうがいいと思うけど、軽くばーっと出したいときに使えるわざということで。

まぁ、当たり前に近い内容かもしれないし、わざわざ書くほどのことでもないかもしれないけど、アウトプットを重視してみたり。
多分、awk使いたいだけだった…

P.S.
気が向いたら、grepとawkで正規表現の処理速度の違いとか調べてみるとよいかもしらん。いくらでも上のコードスマートできると思いまする。fgrep -vして、さらにawkで正規表現とか無意味というか、すごい無駄な気がするので。