awk v.s. bashどっちが強い?@osc2011tokyo

34
「シェルスクリプト VS AWKどっちが強い!? プログラミングバトル 日本 gnu awk ユーザー会 斉藤博文 USP友の会 上田隆一

Upload: ryuichi-ueda

Post on 13-Nov-2014

6.925 views

Category:

Technology


0 download

DESCRIPTION

OSC2011 Tokyo/Fallで、日本gnu awkユーザー会の斉藤さんと行ったプレゼンテーションです。awkとbashの馴れ合い、もとい、共存共栄がテーマです。

TRANSCRIPT

Page 1: awk v.s. bashどっちが強い?@OSC2011Tokyo

「シェルスクリプト VS AWK」 どっちが強い!?

プログラミングバトル

日本 gnu awk ユーザー会 斉藤博文

USP友の会 上田隆一

Page 2: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 2

この発表

• awk と シェルスクリプト(bash) の対決– どっちが強い?(小学生風)

– 同じお題をawkとシェルスクリプトで書く• スクリプトの華麗さを競う

– 対決者• awk: 斉藤博文(日本 gnu awk ユーザー会)

– @hi_saito

• シェルスクリプト: 上田隆一(USP友の会)– @usptomo, @ryuichiueda

Page 3: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 3

awk

• 1977 年にできたスクリプト言語– GNU awk は 1985 年

• UNIX の創造者の英知の集合– Alfred Aho– Peter Weinberger

– Brian Kernighan

• 実は awk は高速– nawk << Ruby, Perl < gawk << mawk << C

Page 4: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 4

bashスクリプト• シェルスクリプト

– 手で端末に打つコマンドをファイルに書くだけ

• bash– Linux標準、使ったこと無い人はいないはず

• コマンド使い放題– 超高級プログラミング言語としての側面

• 処理の大半はコマンドに任せる

• bashを端末を叩く人はみんなプログラマアイコン?マスコット?

んなもん無い。

Page 5: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 5

本日のお題

• Round 1 小技: apache logさばき

• Round 2 中技: CGIで何かアピール

• Round 3 フリー演技

Page 6: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 6

FS にダブルクォート (") を使え!

1回の表 (ノーアウト)

• ダブルクォートを FS にすると・・・– $1:アクセス元、日付

– $2: 受け取ったコマンド

– $3: ステータスコード

– $6: クライアント情報

Apache のログ解析の極意

ほとんどの解析が便利になるよ!

Page 7: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 7

awk だけに頼るな!

1回の表 (1 アウト)

• awk だけで書こうとすると結構大変かも。

• shell のパイプで繋げるとデバッグもしやすいね。

ログ解析の極意

最も多く 404 を返しているサイトを探せ!

御題

Page 8: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 8

1回の表 (2 アウト)#! /bin/gawk -fBEGIN { FS = "\"";}$3 ~ / 404 / { split($1, arr, / /); count[arr[1]]++;}END { for (a in count) { stat_arr[i++] = sprintf("%010s", count[a]) " " a; } num = asort(stat_arr); split(stat_arr[num], url, / /); print url[2];}

awk だけでできるけど、直感的じゃないよね。

Page 9: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 9

1回の表 (2 アウト)

$ cat access_log | \ awk -F '"' '$3 ~ / 404 /' | \ awk '$0 = $1' | \ sort | \ uniq -c | \ sort -nr | \ awk 'NR == 1 && $0 = $2'

127.0.0.1 # オレかよ!!

分かりやすいし、途中結果も確認しやすいね。

Page 10: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 10

system() は fflush() することをうまく使え!

1回の表 (2 アウト)

バッファに溜まって出力されない?

$ tail -f access_log |\ awk '{system ("dig -x" $1 " +short")}'

リアルタイムで IP アドレスからホスト名を引け!

御題

Page 11: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 11

1回の裏• シェルスクリプトでのログ処理

– データを正規化しておくと以後の処理が簡単に000003795 1 114.182.31.102000003795 2 -000003795 3 -000003795 4 20111106 162032000003795 5 GET /usage/ctry_usage_201110.png HTTP/1.1000003795 6 200000003795 7 4168000003795 8 http://www.araibo.com/usage/usage_201110.html000003795 9 Mozilla/5.0 (X11; Linux i686; rv:7.0.1) Gecko/20100101 Firefox/7.0.1000003796 1 66.249.66.18000003796 2 -000003796 3 -000003796 4 20111106 164022000003796 5 GET /paper/ARAIBO_TechnicalReport2006.pdf HTTP/1.1000003796 6 200000003796 7 1801153000003796 8 -000003796 9 Googlebot/2.1 (+http://www.google.com/bot.html)

Page 12: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 12

1回の裏• 正規化スクリプト

– ...結構awk依存#!/bin/bash -vxdir=/var/www/html/OSCtmp=/tmp/$$

cat $dir/LOG/httpd/access_{log.*,log} |sed -e 's/\(..*\) \(..*\) \(..*\) \[\(..*\)\] "\(..*\)" \(..*\) \(..*\) "\(..*\)" "\(..*\)"$/\1ダァシェリイェス\2ダァシェリイェス\3ダァシェリイェス\4ダァシェリイェス\5ダァシェリイェス\6ダァシェリイェス\7ダァシェリイェス\8ダァシェリイェス\9/' |awk -F"ダァシェリイェス" '{c=1;for(i=1;i<=NF;i++){print NR,c++,$i}}' |awk '{$1=sprintf("%09s",$1);print}' > $tmp-data

awk '$2==4' $tmp-data | tr '/:' ' ' |awk '{print $4,$0}' |sed -f $dir/SYS/MONTH |awk '{print $2,$3,$6$1$4,$7$8$9}'| sort -ms -k1,2 - $tmp-data |awk '$2!=4 || $3!~/:/' > $dir/LOG/ACCESS_LOG

Page 13: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 13

1回の裏

• 続きは端末で– 404エラーを出したIP

• $ cat ../LOG/ACCESS_LOG | awk '$2==1 || $2==6 ' | awk '{if($2==1){printf("%s ",$0)}else{print}}' | grep "404$" | awk '{print $3}' | sort | uniq -c | awk '{print $2,$1}' | sort -k2,2n

– 閲覧された回数• $ awk '$2==5' ../LOG/ACCESS_LOG | awk '{print $4}' | sort | uniq

-c | egrep "cgi|php|htm|html" | awk '{print $2,$1}' | sort -k2,2n

※難しいでしょうか??いや、出力見ながらパイプをつなげていくだけなので、案外簡単です。

Page 14: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 14

GET と POST を意識せよ!

2回の表 (ノーアウト)

awk で CGI を作る時の極意

最近の LL だと GET と POST を意識しなければいけないのはオワコンかもしれないけど、知って損なし。

Page 15: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 15

2回の表 (1 アウト)

• 体重を入力すると、グラフにしていってくれる。

• スマートフォンでアプリ化するほどのものでもないよね。

日々の体重を記録せよ!

御題

Page 16: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 16

2回の表 (1 アウト)

• 手軽

• テキストベースで扱える

• 出力の種類が多い

Gnuplot を使いこなせ!

グラフの極意

munin とか Webalizer のようなものも作れる!

Page 17: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 17

2回の表 (2 アウト)

<html><head><title>AWK の CGI サンプル</title></head><body><form method="GET" action="graph.cgi"><input type="text" value="60" name="weight"><input type="submit" value="get" name="submit"></form></body></html>

これは普通の HTML です。

Page 18: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 18

2回の表 (2 アウト)

#! /bin/gawk -f## graph.cgiBEGIN { data_file = "data.txt"; ORS = "\r\n"; split(ENVIRON["QUERY_STRING"], arr_query, "&"); for (i in arr_query) { split(arr_query[i], arr_query_val, "="); query_name = arr_query_val[1]; query_str = arr_query_val[2]; query[query_name] = query_str; }

GET なので環境変数からデータを格納する。

Page 19: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 19

2回の表 (2 アウト)

now = strftime("%Y/%m/%d-%H:%M"); printf("%s %s\n", now, query["weight"])>>data_file; close(data_file); print "\set xdata time\n\set timefmt '%Y/%m/%d-%H:%M:%S'\n\set terminal png\n\set yrange [0:100]\n\set xlabel 'Date'\n\set ylabel 'Weight (Kg)'\n\set output 'graph.png'\n\plot '" data_file "' using 1:2 title 'Weight' with lines\n\quit\n\" | "gnuplot > /dev/null";

データを格納し、Gnuplot でグラフを描く。

Page 20: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 20

2回の表 (2 アウト)

print "Content-Type: text/html"; print ""; print "\<html>\<head>\<title>体重のグラフ</title>\</head>\<body>\<img src='graph.png'>\</body>\</html>\";}

HTML を出力し、画面にグラフを表示する。

詳細は

ブースに

Go!

Page 21: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 21

2回の裏

• テキストの表をブラウザに出力してみる。– コマンドにしてみました。

#!/bin/bashecho '<table cellspacing="0" border="1">'sed -e 's;^;\t<tr>\n\t\t<td>;'\ -e 's;$;</td>\n\t</tr>;'\ -e 's; ;</td>\n\t\t<td>;g' < /dev/stdinecho '</table>'

html_tableコマンド

Page 22: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 22

2回の裏• すごく頑丈なアクセスカウンタを作ってきました。

– HTTP出力込みでわずか6行

–原理

• アクセスがあるとカウンタファイルを1バイト増やす

• lsでカウンタファイルの容量を調べて出力

• 排他処理なんてイラネエ。あ、awkを使ってもうた。

#!/bin/bash -vxdir=/home/usp/ACCESS_COUNTERecho -n 1 >> $dir/POMPA/COUNTERecho "Content-type: text/html\n"ls -l $dir/POMPA/COUNTER | awk '{print $5}'exit 0

Page 23: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 23

2回の裏• ドリルダウン機能つきの表(USP研究所のデモから)

– bashで書いたCGIスクリプト• ユーザの操作履歴をPOSTで受ける

• 操作履歴から表示するレコード、開閉ボタンを準備

• htmlのテンプレートに貼り付けて出力

もっと派手なものが見たければブースへ!!

Page 24: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 24

3回の表 (そして伝説へ・・・)

igawk は 100 % shell なので注意!

gawk で @include する極意!

• 中間ファイルを作成しないように、直接ソースを gawk に食わせているため、巨大なスクリプトを実行するとエラーになる。orz

– comp.lang.awk の FAQ ・・・

eval gawk $opts -- '"$processed_program"' '"$@"'

Page 25: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 25

3回の表 (そして伝説へ・・・)

好きな言語で記述せよ!

電卓を作る極意!

calc() {awk "BEGIN {print $*}"}

• これ、マジ便利です!

• Perl, Ruby, Python, etc. 自分の好きな言語でどうぞ!

Page 26: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 26

3回の表 (そして伝説へ・・・)

100 % ネタです!

shell を作る極意!

awk '{system($0)}'

Page 27: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 27

3回の表 (そして伝説へ・・・)

length() は length でエラーにならない! 

ppencode の極意!

0 : length1 : cos(length)2 : int(exp(cos(length)))3 : ...

• length が引数なしでエラーにならないのはバグとして報告されているので、いつか使えなくなるかも?

詳細は

ブースに

Go!

Page 28: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 28

3回の表 (そして伝説へ・・・)

根気と気合です!

CMS を作る極意!

• 全て awk で記述された Blis を改良し、RSS も生成するようにしてある。

詳細は

ブースに

Go!

Page 29: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 29

3回の表 (そして伝説へ・・・)

文字コードを UTF-8 に揃えよ!

ImageMagick を扱う極意!

• UTF-8 ならコマンドラインから文字列を指定して、年賀状とか書けちゃうよ。

詳細は

ブースに

Go!

Page 30: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 30

3回裏(伝説なのか?)• 他の言語を使う。

– PYTHON.sh, C.sh, RUBY.sh, ...

#!/bin/bash# エクセルシートのB列の値を足す。ruby << FIN | awk 'BEGIN{sum=0}{sum+=$1}END{print sum}'require 'rubygems'require 'spreadsheet'book = Spreadsheet.open './hoge.xls'sheet = book.worksheet 0for i in 0..3 print sheet[i,1] print "\n"endFIN

Page 31: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 31

3回裏(伝説なのか?)

• webから数値参照で書かれた文字列を取ってくる。

#!/bin/bash

curl $1 |grep '&#' |w3m -dump -T text/html

Page 32: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 32

3回裏(伝説なのか?)

• クローラを作ってきました。#!/bin/bash -vxmkdir -p ./cachecd ./cacheecho 'http://www.google.co.jp/' > ./url.1for i in 2 3 4 ; do cat ./url.$(( $i - 1 )) | wget -i - cat ./* | sed -e 's|href="\([^"][^"]*\)"|\n\1\n|g' | grep ^http | sort | uniq                    > ./url.$idone

exit 0

Page 33: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 33

3回裏(伝説なのか?)

• ブースにて、bashで書かれたシステムをお見せします。

Page 34: awk v.s. bashどっちが強い?@OSC2011Tokyo

2011年11月19日 OSC2011 Tokyo Fall 34

まとめ

• awkなしでシェルスクリプトを書くのは大変だね

• シェルスクリプトと awk で世界が広がるよ– ということで友好団体になりました。

• 質問はブースへ–隣同士にいます。