sort(並べ替え)・uniq(重複除去)・wc(数え上げ)は、grepやawkと並ぶテキスト処理の基本コマンドです。単体でも便利ですが、パイプでつないだときに真価を発揮します。とくにsort | uniq -c | sort -rnという並びは、「ログの中で一番多く出てきた値は何か」を調べる頻度ランキングの定番パターンで、覚えておくと様々な場面で使い回せます。
つまずきやすいのは、数字を並べ替えたのに数値順にならないことと、uniqだけでは重複が消えないことです。どちらも「なぜそうなるか」を理解すれば怖くありません。この記事では、実機のLinux(WSLのDebian)で実際に数字が意図通りに並ばない様子や、重複が消えない様子を再現しながら、3つのコマンドを整理します。
sortは既定で文字列として並べ替えます。数値順にするには-nが必要です。uniqは隣接した重複だけを消します。先にsortしてから使うのが鉄則です。- 件数を数えるには
uniq -c。sort | uniq -c | sort -rnで頻度ランキングが作れます。 wcは行数・単語数・バイト数を数えます。行数だけならwc -lです。sort -uは、並べ替えと重複除去を1コマンドで行います。- CSV的なデータは
sort -t区切り文字 -kフィールド番号で特定の列を基準に並べ替えられます。
ログの絞り込みはgrep、列の抽出・集計はawk、パイプの仕組みはリダイレクトとパイプもあわせて参考になります。
sortの基本と数値ソートの罠
sortはファイルの行を並べ替えます。何も指定しないと「文字列」として比較されるため、数字が並んでいても期待どおりの数値順にならないことがあります。
# 通常の sort(文字列として比較) cat nums.txt # 30 # 5 # 100 # 2 sort nums.txt # 100 ← "1" が "2" より小さい文字として扱われるため先頭に来る # 2 # 30 # 5 # -n を付けると数値として正しく並ぶ sort -n nums.txt # 2 # 5 # 30 # 100
実機で、30, 5, 100, 2という並びのファイルに-nなしのsortをかけると、結果は100, 2, 30, 5という、数値としては奇妙な順序になりました。これはsortが各行を「文字列」として先頭の文字から比較するためで、"100"は先頭が"1"なので"2"より前に来てしまいます。-n(数値として比較)を付けると、期待どおり2, 5, 30, 100という数値順になりました。「並べ替えたのに順番がおかしい」ときは、ほぼ必ずこの-n忘れが原因です。ファイルサイズやアクセス数など、数字を扱うときは-nを付ける習慣をつけてください。
逆順(-r)とユニーク(-u)
降順にしたいときは-rを追加します。-nと組み合わせれば数値の大きい順にできます。また、並べ替えと重複除去を同時に行う-uも便利です。
# 数値の大きい順(-n と -r を組み合わせる) sort -nr nums.txt # 100 # 30 # 5 # 2 # -u: 並べ替えながら重複行も除去する sort -u notsorted.txt # apple # banana
実機でも、-rを付けると既存の並び順(このケースでは文字列順)が反転し、-nr(数値かつ逆順)にすると100, 30, 5, 2という数値の大きい順になりました。またsort -uを使うと、並べ替えと重複除去を1コマンドで済ませられることも確認しました(次で説明するsort | uniqと同じ結果が1コマンドで得られます)。「とりあえず並べ替えて重複も消したい」だけならsort -uが最短です。
【最重要】uniqは隣接した重複だけを消す
uniqは重複行を1つにまとめるコマンドですが、「隣り合っている行」だけを比較します。ファイル全体を通して同じ行がバラバラの位置にある場合、uniq単体では消えません。
cat notsorted.txt # apple # banana # apple # uniq だけでは、離れた場所にある重複が残る uniq notsorted.txt # apple # banana # apple ← 消えていない!(隣り合っていないため) # 先に sort でまとめてから uniq を使う(定番の組み合わせ) sort notsorted.txt | uniq # apple # banana
実機で、apple・banana・appleという(隣り合っていない)重複を含むファイルにuniqだけをかけたところ、3行のまま変わらず、2つ目のappleは消えませんでした。uniqは「直前の行と同じかどうか」しか見ていないため、離れた場所にある同じ行には無力です。sort notsorted.txt | uniqのように先に並べ替えて同じ行を隣接させてからuniqにかけると、期待どおりapple・bananaの2行に減りました。「重複を消したいなら、まずsort」——この鉄則を知らないと、「uniqを使ったのに重複が残っている」という混乱に必ず出会います。
件数集計(uniq -c)と頻度ランキング
uniq -cを使うと、各行が何回登場したかを数えられます。これとsortを組み合わせれば、「一番多く出てきた値」ランキングが作れます。ログ分析の定番パターンです。
cat dup.txt # apple # apple # banana # banana # banana # cherry # -c で件数を数える(sort してからが前提) sort dup.txt | uniq -c # 2 apple # 3 banana # 1 cherry # さらに件数の多い順に並べ替える(頻度ランキングの完成形) sort dup.txt | uniq -c | sort -rn # 3 banana # 2 apple # 1 cherry
実機でも、sort | uniq -cで各値の出現回数(apple: 2件・banana: 3件・cherry: 1件)が取得でき、さらに| sort -rnを足すと件数の多い順(banana→apple→cherry)に並べ替わりました。sort | uniq -c | sort -rnという3段のパイプは、「何が一番よく出てくるか」を調べる定番の型です。アクセスログのIPアドレス集計、エラーメッセージの頻度調査、よく使われる単語の集計など、幅広い場面で使い回せます。awkで特定の列だけ抜き出してから、この3段パイプに渡す組み合わせも実務でよく使われます。
wc(行数・単語数・バイト数)
wc(word count)は、行数・単語数・バイト数を数えます。オプションなしだと3つとも表示され、行数だけ欲しいときは-lを付けます。
# オプションなし: 行数 単語数 バイト数 の順で表示 wc fruits.txt # 4 4 26 fruits.txt # 行数だけ wc -l fruits.txt # 4 # パイプの結果を数えるときは < でリダイレクトするとファイル名が付かず読みやすい wc -l < fruits.txt # 4 # 単語数だけ / バイト数だけ wc -w fruits.txt wc -c fruits.txt
実機でも、wc fruits.txtで「4行・4単語・26バイト」が一度に表示され、wc -lで行数だけが取得できました。findで見つけたファイルの数を数えたり、grepでヒットした行数を数えたりと、| wc -lで締めくくるパイプは非常に多く登場します。wc -l < ファイルのようにリダイレクトで渡すと、出力にファイル名が付かず数字だけになるので、変数に代入するときに便利です。
特定の列でソートする(-t / -k)
CSVのようなデータで、特定の列(フィールド)を基準に並べ替えたいときは、区切り文字を-t、対象の列番号を-kで指定します。
cat csv.txt # taro,30 # hanako,25 # jiro,40 # -t, で区切り文字をカンマに、-k2 で2列目、-n で数値として比較 sort -t, -k2 -n csv.txt # hanako,25 # taro,30 # jiro,40
実機でも、sort -t, -k2 -n csv.txtを実行すると、2列目(年齢)を数値として比較した昇順(hanako 25 → taro 30 → jiro 40)に並び替わりました。-tで「何を区切りとみなすか」、-kで「何列目を基準にするか」を指定でき、-nを足せばその列を数値として比較します。名前順ではなく年齢順、日付順など、特定の列を基準に並べ替えたいCSV的なデータに威力を発揮します。
主な書き方一覧
sort・uniq・wcの要点をまとめます。
| 書き方 | 働き |
|---|---|
sort / sort -n |
文字列として並べ替え / 数値として並べ替え |
sort -r / -u |
逆順 / 重複除去つき |
sort -t, -k2 -n |
区切り文字とフィールド番号を指定 |
uniq |
隣接した重複行を1つに(sortとセット) |
uniq -c |
各行の出現回数を数える |
sort | uniq -c | sort -rn |
頻度ランキングの定番パターン |
wc / wc -l |
行数・単語数・バイト数 / 行数だけ |
よくある失敗
数字を並べ替えたのに順番がおかしい
既定では文字列として比較されます。数値順にしたいときは-nを付けます。
uniqだけでは重複が消えない
uniqは隣接した行しか見ません。先にsortしてから使います。
uniq -cの前にsortを忘れる
件数集計も同様に、離れた同じ行は別々に数えられてしまいます。sort | uniq -cの順で使います。
wcの出力にファイル名が邪魔になる
wc -l ファイルだとファイル名も出ます。wc -l < ファイルにすると数字だけになります。
-kのフィールド番号を1始まりと勘違いしない
-k2は2列目を指します(1列目から数えます)。区切り文字の指定-tを忘れないようにします。
よくある質問
sortは行を「文字列」として比較するため、100が2より前に来るなど、数値として奇妙な順序になることがあります。sort -nを使うと数値として正しく比較され、期待どおりの順序になります。実機でも、-nの有無でこの違いを確認しています。uniqは「隣接した行」同士しか比較しないためです。ファイル内の離れた場所に同じ行があっても、uniq単体では消えません。先にsortで同じ行を隣り合わせにしてからuniqにかけてください(sort file | uniq)。実機でも、sortを挟まないと重複が残ることを確認しています。sort ファイル | uniq -c | sort -rnという組み合わせが定番です。uniq -cで各行の出現回数を数え、sort -rnで件数の多い順に並べ替えます。実機でも、この3段のパイプで正しく頻度ランキングが作れることを確認しています。wc -l ファイル名を使います。パイプの結果の行数を数えたいときはコマンド | wc -lとつなぎます。ファイル名を出力に含めたくない場合はwc -l < ファイル名のようにリダイレクトで渡すと、数字だけが表示されます。sort -t区切り文字 -kフィールド番号 ファイルを使います。たとえばカンマ区切りの2列目を数値として並べ替えるならsort -t, -k2 -n ファイルです。実機でも、この指定で2列目(年齢など)を基準にした正しい並べ替えができることを確認しています。まとめ
sortは既定で文字列比較。数値順には-nが必須です。uniqは隣接した重複だけを消します。必ずsortしてから使います。sort | uniq -c | sort -rnで頻度ランキングが作れます。wc -lで行数、区切り文字・列指定はsort -t -k。sort -uなら並べ替えと重複除去が1コマンドで済みます。
sort・uniq・wcは地味に見えて、ログ分析やデータ集計の土台を支えるコマンドです。「-nを忘れない」「uniqの前にはsort」の2点さえ押さえれば、grepやawkと組み合わせて、テキストデータを自在に集計・分析できるようになります。
