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

問3 このファイルからserver4の行だけ表示しろ

○○の行を表示する->grepでやるのが早い。

grep server4 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

多分もっといいやり方あるとおもいます。