ログファイルの解析やデータ集計では、「並べ替えて重複を除く」という操作が頻繁に登場します。
sort と uniq はこの作業をコマンドラインで手軽に行うための定番ツールです。
パイプで組み合わせることで、複雑な集計もワンライナーで実現できます。
sortコマンドの基本
sort はテキストファイルの各行をアルファベット順(または数値順)に並べ替えます。
sort ファイル名
試しに、以下の内容を fruits.txt として用意してみましょう。
cat fruits.txt
banana
apple
cherry
apple
mango
banana
sort を実行すると行がアルファベット順に並びます。
sort fruits.txt
apple
apple
banana
banana
cherry
mango
よく使うsortオプション
逆順に並べ替える(-r)
sort -r fruits.txt
mango
cherry
banana
banana
apple
apple
数値として並べ替える(-n)
文字列としてではなく数値の大小で並べ替えます。-n なしだと 10 が 2 より前に来てしまうため、数字を扱うときは必ず指定します。
echo -e "10\n2\n30\n5" | sort
10
2
30
5
echo -e "10\n2\n30\n5" | sort -n
2
5
10
30
特定の列を基準に並べ替える(-k)
スペース区切りのデータで2列目を基準にしたい場合:
cat scores.txt
alice 85
bob 92
carol 78
dave 92
sort -k2 -n scores.txt
carol 78
alice 85
bob 92
dave 92
重複行を除きながら並べ替える(-u)
-u(unique)オプションを使うと、並べ替えと同時に重複行を削除できます。
sort -u fruits.txt
apple
banana
cherry
mango
uniqコマンドの基本
uniq は連続する重複行を削除します。重要なのは、uniq は隣り合う行しか比較しない点です。そのため、通常は sort と組み合わせて使います。
sort fruits.txt | uniq
apple
banana
cherry
mango
よく使うuniqオプション
重複した行の出現回数を数える(-c)
ログ解析などで「何回出現したか」を調べるときに便利です。
sort fruits.txt | uniq -c
2 apple
2 banana
1 cherry
1 mango
出現回数の多い順に並べたい場合は、sort -rn を追加します。
sort fruits.txt | uniq -c | sort -rn
2 banana
2 apple
1 mango
1 cherry
重複している行だけを表示する(-d)
sort fruits.txt | uniq -d
apple
banana
重複していない行だけを表示する(-u)
sort fruits.txt | uniq -u
cherry
mango
実践例:アクセスログの集計
Webサーバーのアクセスログから、アクセス数の多いIPアドレスを上位5件表示する例です。
# access.log の1列目がIPアドレスと仮定
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -5
このコマンドチェーンを分解すると:
awk '{print $1}'→ IPアドレスの列だけ取り出すsort→ uniq のために隣接させるuniq -c→ 出現回数を集計sort -rn→ 出現回数の多い順に並べ替えhead -5→ 上位5件だけ表示
練習問題
以下の内容を access.log として保存して問題に挑戦してください。
192.168.1.10 GET /index.html
192.168.1.20 GET /about.html
192.168.1.10 GET /contact.html
192.168.1.30 GET /index.html
192.168.1.20 POST /login
192.168.1.10 GET /index.html
192.168.1.30 GET /about.html
192.168.1.20 GET /index.html
問題1: アクセスしたIPアドレスの一覧を重複なしで表示してください(順不同でも可)。
問題2: どのIPアドレスが最もアクセスしているか(件数付きで)表示してください。
問題3: アクセスされたURLの一覧を重複なしで表示してください。
解答
問題1の解答
awk '{print $1}' access.log | sort -u
192.168.1.10
192.168.1.20
192.168.1.30
問題2の解答
awk '{print $1}' access.log | sort | uniq -c | sort -rn
3 192.168.1.10
3 192.168.1.20
2 192.168.1.30
192.168.1.10 と 192.168.1.20 が3件で並んでいます。
問題3の解答
awk '{print $3}' access.log | sort -u
/about.html
/contact.html
/index.html
/login