- 2005-02-16 (Wed) 04:32
- プログラミング ( sed/wake/awk )
AWK の勉強のためとの建前で 第2回東方最萌トーナメント の集計スクリプトを書いてみた.スレッドの番号を入れると wget でページを落としてきて解析して gnuplot でグラフを描いてくれる.あほだ...
ついでなのでコードでも書いておいてみよう.
メインは cnt.sh.
gnuplot があればグラフもはく.
(ソース中のコマンドは pgnuplot になってる)
cnt.sh:
DATAFILE=\"data.dat\"
RESULTFILE=\"result.txt\"
CH1DAT=\"ch1.dat\"
CH2DAT=\"ch2.dat\"
CH1DATTIME=\"ch1time.dat\"
CH2DATTIME=\"ch2time.dat\"
GPLFILE=\"plot.gpl\"
BBSADDR=\"http://jbbs.livedoor.jp/bbs/read.cgi/game/20311/\"
GRAPHMAXY=800
CH1=$1
CH2=$2
DAT=$3
shift
shift
shift
echo -n \"\" > $DATAFILE
cnt=$1
shift
while [ $cnt -gt 0 ]
do
echo $1
echo $cnt
mv $DATAFILE tmp.dat
cat tmp.dat $1 >> $DATAFILE
shift
cnt=`expr $cnt - 1`
done
for i in $*
do
rm $i
wget $BBSADDR$i
mv $DATAFILE tmp.dat
cat tmp.dat $i >> $DATAFILE
done
./count.sh $CH1 $CH2 $DAT $DATAFILE > $RESULTFILE
cat $RESULTFILE | nkf --euc | awk -f split.awk -v TARGET=\"1st\" | nkf --sjis > $CH1DAT
cat $RESULTFILE | nkf --euc | awk -f split.awk -v TARGET=\"2nd\" | nkf --sjis > $CH2DAT
cat $RESULTFILE | nkf --euc | awk -f split.awk -v TARGET=\"acc\" | nkf --sjis
cat $RESULTFILE | nkf --euc | awk -f split.awk -v TARGET=\"1stTime\" | nkf --sjis > $CH1DATTIME
cat $RESULTFILE | nkf --euc | awk -f split.awk -v TARGET=\"2ndTime\" | nkf --sjis > $CH2DATTIME
echo -n \"\" > $GPLFILE
echo \"set terminal postscript eps color solid lw 1\" >> $GPLFILE
echo \"set output \\"graph-$CH1-$CH2.eps\\"\" >> $GPLFILE
echo \"set key left\" >> $GPLFILE
echo \"set boxwidth 0.3 relative\" >> $GPLFILE
echo \"set xdata time\" >> $GPLFILE
echo \"set timefmt \\"%H:%M\\"\" >> $GPLFILE
echo \"set format x \\"%H:%M\\"\" >> $GPLFILE
echo \"set xrange [\\"00:00\\":\\"23:10\\"]\" >> $GPLFILE
echo \"set xtics \\"00:00\\", 10800, \\"24:00\\"\" >> $GPLFILE
echo \"set yrange [0:$GRAPHMAXY]\" >> $GPLFILE
echo \"set multiplot\" >> $GPLFILE
echo \"set style data lines\" >> $GPLFILE
echo \"set style line 1 lw 3\" >> $GPLFILE
echo \"set style line 3 lw 3\" >> $GPLFILE
echo \"plot \\"ch1.dat\\" using 1:2 ls 1 title \\"$CH1\\", \\"ch2.dat\\" using 1:2 ls 3 title \\"$CH2\\"\" >> $GPLFILE
echo \"set style data boxes\" >> $GPLFILE
echo \"plot \\"ch1time.dat\\" using ((\$1*60+20)*60):2 ls 1 title \\"\\", \\"ch2time.dat\\" using ((\$1*60+40)*60):2 ls 3 title \\"\\"\" >> $GPLFILE
echo \"unset multiplot\" >> $GPLFILE
echo \"set output\" >> $GPLFILE
pgnuplot $GPLFILE
split.awk:
BEGIN { FLAG=0 STARTPat=\"Start of \"TARGET ENDPat=\"End of \"TARGET } //{ if($0 == ENDPat){ FLAG = 0 } if(FLAG) print if($0 == STARTPat){ FLAG = 1 } }
count.awk:
BEGIN {
RS = \"<dt>\"
# 環境から取得
ch1str=ENVIRON
CH1STR# キャラ名1 ch2str=ENVIRON
CH2STR# キャラ名2 ch1all=ENVIRON
CH1ALL# キャラ名リスト1 ch2all=ENVIRON
CH2ALL# キャラ名リスト2 date=ENVIRON
DATE# 日付 split(ch1all,ch1,\";\") # 配列に直す split(ch2all,ch2,\";\") print \"Date: \" date print \"Ch1: \" ch1str print \"Ch1All: \" ch1all print \"Ch2: \" ch2str print \"Ch2All: \" ch2all } //{ # 日付チェック if($0 !~ date) next # レス番号 pos=match($0, /<a [^>]*>[0-9]+<\/a>/) if(!pos) next resnum = substr($0, pos, RLENGTH) gsub(/<a [^>]*>/, \"\", resnum) gsub(/<\/a>/, \"\", resnum) if((resnum+0) < 5 || (resnum+0) > 950) next # 同一レス内二重投稿チェック str=$0 numofent=gsub(/<<([^&]*)>>/, \"\", str) if(numofent == 0 || numofent>1) next # code チェック pos=match($0, /\[\[([^\]]*)\]\]/) if(!pos) next str = substr($0, pos, RLENGTH) if(codes[str]) { codes[str]++;
} else {
codes[str]++;
}
# 取り出し
pos=match($0, /<<([^&]*)>>/)
if(!pos) next
str = substr($0, pos, RLENGTH)
gsub(/<|>/, \"\", str)
# カウント
for(i in ch1){
if(str ~ ch1[i]){
ch1s[str]++
str = ch1str
break
}
}
for(i in ch2){
if(str ~ ch2[i]){
ch2s[str]++
str = ch2str
break
}
}
array[str]++
# 時間での統計
pos=match($0, /[0-9][0-9]:[0-9][0-9]/)
if(!pos) next
timestr = substr($0, pos, RLENGTH)
split(timestr,times,\":\")
if(str ~ ch1str){
acc1[array[str]] = timestr
acc1h[times[1]+1] = array[str]
}
if(str ~ ch2str){
acc2[array[str]] = timestr
acc2h[times[1]+1] = array[str]
}
}
END {
# 最終統計データ
print \"Start of acc\"
print array[ch1str] \" : \" ch1str
print array[ch2str] \" : \" ch2str
print \"Others...\"
for(i in array){
if(ch1str ~ i) continue
if(ch2str ~ i) continue
print array[i] \" : \" i
}
#使った名前出力
names=ch1str
sep = \"::\"
for(i in ch1s){
names=names sep i
sep=\";\"
}
print names
names=ch2str
sep = \"::\"
for(i in ch2s){
names=names sep i
sep=\";\"
}
print names
# code 重複の出力
for(i in codes){
if((codes[i]+0)>1){
print i \" \" codes[i]
}
}
print \"End of acc\"
# キャラ1の名前リスト
print \"Start of 1stName\"
for(i in ch1s){
print i \" \" ch1s[i]
}
print \"End of 1stName\"
# キャラ2の名前リスト
print \"Start of 2ndName\"
for(i in ch1s){
print i \" \" ch2s[i]
}
print \"End of 2ndName\"
# キャラ1の時間統計
print \"Start of 1st\"
for(i = 1; i <= array[ch1str]; i++){
print acc1[i] \" \" i
}
print \"End of 1st\"
# キャラ2の時間統計
print \"Start of 2nd\"
for(i = 1; i <= array[ch2str]; i++){
print acc2[i] \" \" i
}
print \"End of 2nd\"
# キャラ1の時間統計
print \"Start of 1stTime\"
print 0 \" \" acc1h[1]
for(i = 2; i <= 22; i++){
print (i-1) \" \" (acc1h[i] - acc1h[i-1])
}
print 22 \" \" (acc1h[24] - acc1h[22])
print \"End of 1stTime\"
# キャラ2の時間統計
print \"Start of 2ndTime\"
print 0 \" \" acc2h[1]
for(i = 2; i <= 22; i++){
print (i-1) \" \" (acc2h[i] - acc2h[i-1])
}
print 22 \" \" (acc2h[24] - acc2h[22])
print \"End of 2ndTime\"
}
count.sh:
export CH1STR=$1
export CH2STR=$2
EXECAWK=\"awk -F :: /$1/{print\$2}\"
export CH1ALL=`cat names.txt | $EXECAWK`
EXECAWK=\"awk -F :: /$2/{print\$2}\"
export CH2ALL=`cat names.txt | $EXECAWK`
export DATE=$3
cat $4 | nkf --euc | awk -f count.awk | nkf --sjis
name.txt:
Reimu::霊夢;巫女;夢;神社;結界;reimu;28.6%;ハクレイのミコ;ハクレー;紅白;ミコミコレイーム;二色刷り;六位;瞬 Alice::アリス;リス;マーガトロイド;人形;七色;alice;ありしゅ;Alice;トロ;蟻さん;ありす;株式会社チャンピオンソフト;蹴りス;チャールズ・ラトウィッジ・ドジスン;カシューチャ;樋口 橘;ホライ Marisa::魔理沙;黒くて;沙;マスタースパーク;Missile;魔法使い;マリ;恋符;恋の;旧ゴキブリ;まりさ;宴会の幹事;黒いの;霧雨;和食派;魔砲使いの人;恋色マジック;禿げ;スターダストレヴァリエ;黒 Fran::フラン;妹;ン
;腐乱;いもーとさま;紅月ふらん;495;ふらんちゃん;レーヴァテイン;乳臭い俺の嫁 Yuyuko::ゆゆさま;西行寺;幽々子;@;ゆゆこ;ゆゆ様;ユユサマー;おまえはすでに死んでいる;西行法師;ユユコサマ Remy::スカーレット;レッド;レミィ;レミリア;れ
;れみり;紅魔;ハート様大ブレイク;クイーン・オブ・ミッドナイト;姉紅;姉様;スピア・ザ・グングニルの使い手
- Newer: AWK - はじめ