Re:シェル操作課題 (cut, sort, uniq などで集計を行う) 設問編
ymsr先生書いたシェル操作課題 (cut, sort, uniq などで集計を行う) 設問編に答えてみた。環境はzsh。課題のファイルはtest.txtで保存しているという前提で。
問1 このファイルを表示しろ
more test.txt
more派です。
問2 このファイルからサーバー名とアクセス先だけ表示しろ
課題のファイルがサーバー名,unixtime,ユーザーID,アクセス先の形式なので1番目と4番目を表示すればよいのでawkつかう。awkのセパレータはデフォルトではスペースやタブなのでFS=","でカンマに設定する。どこを表示したいかは$1などで指定する。
awk 'BEGIN {FS=","} {print $1","$4}' test.txt
問4 このファイルの行数を表示しろ
行数だけならばwcでOKなんだけど環境によってwcの出力結果は違うので注意。
wc test.txt --結果 9 9 302 test.txt
こうすると左から順に行数、単語数、バイト数、ファイル名。行数だけなら-lオプションをつける。
wc -l test.txt --結果 9 test.txt
ファイル名もいらねーよ。クソが。という場合はこれもawkで切り出す。
wc -l test.txt | awk '{print $1}' --結果 9
問5 このファイルをサーバー名、ユーザーIDの昇順で5行だけ表示しろ
ソートはsortコマンド。セパレータはーtオプションで設定。ソートキーはーkオプションで設定する。先頭5行などはheadコマンドをつかう。
sort -k1,1 -k3,3n -t"," test.txt | head -n 5
この問題の引っかかりやすい所は
sort -k1,3 -t"," test.txt | head -n 5
としてしまうと1,2,3番目のカラムをソートキーにしてしまうこと。今回は1,3番目をソートキーにしたいのでこんな感じにすると
sort -k1 -k3 -t"," test.txt | head -n 5
今度は3番目のキーが辞書順ソートなので30が先頭に来てしまうのでnをつけて数字順ソートにする。
問6 このファイルには重複行がある。重複行はまとめて数え行数を表示しろ
重複分を省きたいときはuniqコマンド。uniqコマンドは同じ行が2つ以上続く時にのみ1行にまとめないのでファイル全体の重複を調べるときはsortしてからuniqする。
sort test.txt |uniq|wc|awk '{print $1}'
最後のawkは行数のみを出すためにかけてる
問7 このログのUU(ユニークユーザー)数を表示しろ
ユーザーIDは3番目のカラムなので抜きだしてソートしてuniqかけてwcで行数カウント。
awk 'BEGIN {FS=","} {print $3}' test.txt | sort |uniq|wc|awk '{print $1}'
問8 このログのアクセス先ごとにアクセス数を数え上位1つを表示しろ
重複行数を出すにはuniqの-cオプション。降順にソートするときはsortの-rオプション。
awk 'BEGIN {FS=","} {print $4}' test.txt | sort | uniq -c | sort -r | head -n1
問9 このログのserverという文字列をxxxという文字列に変え、サーバー毎のアクセス数を表示しろ
基本的には問8と同じ。文字列置換はsedをつかう。
awk 'BEGIN {FS=","} {print $1}' test.txt | sort | uniq -c | sed -e "s/server/xxx/g"
問10 このログのユーザーIDが10以上の人のユニークなユーザーIDをユーザーIDでソートして表示しろ
条件にあうものだけを表示するときはawkで条件式を書く。awk職人の朝は早い・・・
awk 'BEGIN {FS=","} {if($3 >= 10) print $3}' test.txt | sort -n |uniq
ログが数十Gだったら?
こんなところにエントリがあったので紹介しておきます。
http://d.hatena.ne.jp/celitan/20110824/1314176354
多分もっといいやり方あるとおもいます。