sort と uniq の使い方 - データを並べ替えて重複を削る
この記事でできるようになること
- `sort` で行を辞書順・数値順・逆順に並べ替えられる
- `uniq` の前に `sort` が必要な理由を説明できる
- `sort | uniq -c | sort -rn` で頻度ランキングを作れる
前提知識(先に読むと理解しやすい記事)
この記事で学べること
sortで 行を並べ替える 基本操作がわかります。辞書順・数値順・逆順の 3 つですuniqで 重複行を削る 使い方がわかります。「先にsortが要る」という決まりも身につきますsort | uniq -c | sort -rnという 頻度ランキングの定番形 が書けるようになります- 初心者がつまずく 「
uniqだけでは消えない」「数字が変な順に並ぶ」 の理由がわかります
言葉の整理(先に取りちがえを防ぎます)
- 行:ファイルの中の 1 行のことです。改行から改行までのひとかたまりを指します。
- フィールド:1 行の中を空白で区切ったときの、それぞれの部分です。「列」「カラム」もほぼ同じ意味で使われます。この記事では「列」にそろえます。
- 辞書順:文字を 1 文字ずつ左から見くらべる並べ方です。「アルファベット順」「文字列順」も同じものを指します。
- 数値順:行の中身を数として見くらべる並べ方です。辞書順とは結果が変わります。ここが最初の関門です。
- 重複:まったく同じ中身の行が 2 つ以上あることです。
- パイプ:
|の記号です。前のコマンドの結果を、次のコマンドにそのまま渡すしくみです。 - リダイレクト:
>の記号です。画面に出るはずの結果を、ファイルに書き出します。「上書き保存」とは動きがちがう点に注意してください。7-3 でくわしく説明します。
結論(先に覚える型)
- 並べ替えたい →
sort - 並べ替え+重複を消したい →
sort -u - 「何が何回出たか」を集計したい →
sort | uniq -c | sort -rn
前提(対象環境)
- OS:Ubuntu / 一般的な Linux
- GNU coreutils の
sort/uniq(macOS の BSD 版と細部の挙動が異なるオプションあり) - 並べ替えの順番は ロケール(言語と地域の設定)で変わります。この記事の出力は
LC_ALL=Cの場合のものです。LC_ALL=Cは、文字を文字コードの番号どおりに見くらべる設定です
1. まずはここから:行を「並べ替える」とは
結論:
sortは元ファイルを壊さず並べ替え結果を表示する。辞書順・数値順・逆順の 3 つを押さえる。
sort だよ。sort ファイル名 と書くと、1 行ずつ並べ替えて表示 してくれる。サンプルとして次のファイルを用意しよう。
$ cat fruits.txt
banana apple cherry apple banana date
1-1. 基本:辞書順に並べ替える
$ sort fruits.txt
apple apple banana banana cherry date
ポイント
sortは はじめの設定では辞書順 に並べます- 大文字と小文字は、別の文字としてあつかわれます。どちらが先に来るかはロケールで変わります
- 元のファイルは 変わりません。並べ替えた結果を画面に出すだけです
1-2. 逆順(降順)に並べ替える -r
$ sort -r fruits.txt
date cherry banana banana apple apple
-r は reverse(逆)の頭文字です。
2. 数値の並べ替えで初心者がハマる罠
結論:
sortのデフォルトは文字列比較。数値として正しく並べたいときは-nを付ける。
$ cat scores.txt
100 3 25 9 1000
$ sort scores.txt
100 1000 25 3 9
100 が 25 より先に来ています。3 と 9 は最後です。これはバグですか。sort は、はじめの設定では 文字列として 1 文字ずつ左から見くらべる。1 は 2 や 3 より小さい。だから 100 や 1000 が前に来るんだ。-n を付ける。それだけで直るよ。2-1. 数値ソート -n
$ sort -n scores.txt
3 9 25 100 1000
-n は numeric(数値)の頭文字です。
初心者あるある
- ログのサイズや件数を並べるとき、
-nを忘れて変な順序になります - 「数字の列なら
-nを付ける」と覚えておくと事故が減ります
2-2. 数値の大きい順(降順)
$ sort -nr scores.txt
1000 100 25 9 3
-n と -r は 組み合わせられます。ランキングを作るときによく出てくる形です。
3. 並べ替え+重複削除 sort -u
結論:
sort -uは並べ替えと重複削除を 1 コマンドで行う。ユニークな一覧が欲しいときの近道。
$ sort -u fruits.txt
apple banana cherry date
apple と banana が 1 行ずつになりました。-u は unique(一意)の頭文字だよ。sort の結果から重複した行を取りのぞいてくれる。実務では「ユニークな値の一覧が欲しい」場面がとても多いです。sort -u を覚えておくと早く書けます。
4. uniq:重複を削る専門コマンド
結論:
uniqは連続した重複しか削れない。必ずsortの後ろに置く。-cで出現回数を数えられる。
4-1. リナの失敗:uniq だけでは消えない
$ uniq fruits.txt
banana apple cherry apple banana date
apple も banana もまだ重複しています。コマンドが効いていないのでしょうか。uniq は 「となり合っている重複だけ」 を削るんだ。apple が 2 行目と 4 行目にある。間に cherry がはさまっているから、uniq から見ると別のかたまりなんだ。sort する。sort で同じ行を となり合わせ にしてから uniq に渡す。そうすれば重複がきちんと消えるよ。なぜ sort が先に必要なのか
uniq は 1 行ずつ上から読み、直前の行とだけ 見くらべます。ファイル全体を覚えているわけではありません。
そのため、同じ行が離れた場所にあると別ものとして残ります。sort は同じ行をとなり合わせに集めます。だから sort を先に通すと uniq が働けるようになります。
4-2. sort | uniq の組み合わせ
$ sort fruits.txt | uniq
apple banana cherry date
鉄則
uniqは かならずsortの後ろに置きます- 単独で使うのは「すでに並んでいるとわかっているとき」だけです
- 「並べてユニークにする」だけが目的なら、
sort -uのほうが短く書けます
4-3. 各行が何回出たかを数える uniq -c
$ sort fruits.txt | uniq -c
2 apple
2 banana
1 cherry
1 date
-c は count(数える)の頭文字です。行の先頭に 出現回数 が付きます。集計にとても便利です。
4-4. 重複している行だけ・1 回だけの行だけ
# 重複している行だけ表示 $ sort fruits.txt | uniq -d
apple banana
# 1 回しか出ていない行だけ表示 $ sort fruits.txt | uniq -u
cherry date
| オプション | 意味 | 用途 |
|---|---|---|
-c |
カウント付与 | 集計 |
-d |
重複行だけ | 重複している項目を洗い出す |
-u |
ユニーク行だけ | 1 回しか出ない行を抽出 |
-i |
大文字小文字無視 | 表記ゆれをまとめる |
sort にも uniq にも -u があります。ただし意味が少しちがいます。sort -u は「重複を 1 行にまとめる」、uniq -u は「1 回しか出ない行だけを残す」です。取りちがえに気をつけてください。
5. 実務でいちばん使う型:頻度ランキング
結論:
sort | uniq -c | sort -rnの 3 段パイプが頻度ランキングの定番。headで上位 N 件に絞れる。
sort | uniq -c | sort -rn という 3 段パイプ が定番。サンプルログ:
$ cat access.log
192.168.1.10 192.168.1.20 192.168.1.10 192.168.1.30 192.168.1.10 192.168.1.20
頻度ランキング:
$ sort access.log | uniq -c | sort -rn
3 192.168.1.10
2 192.168.1.20
1 192.168.1.30
3 段パイプの分解
| 段 | コマンド | やっていること |
|---|---|---|
| 1 | sort |
同じ行を隣り合わせにする |
| 2 | uniq -c |
隣り合った重複をまとめてカウント付き |
| 3 | sort -rn |
カウント(数値)の大きい順に並べる |
1 段目の sort を省くと、2 段目の uniq -c が数えまちがえます。離れた同じ行を、別のものとして数えてしまうからです。
3 段目でもう一度 sort を使うのは、並べ替える対象が変わるからです。2 段目までは行の中身で並べていました。3 段目では、新しく付いたカウントの数で並べ直します。
5-1. 上位 N 件だけ欲しい
$ sort access.log | uniq -c | sort -rn | head -n 3
head -n 3 で 上位 3 件 にしぼれます。head と組み合わせるのが現場の定番です。
6. キー指定(応用):特定の列で並べ替える -k
結論:
-k2で 2 列目を基準に並べ替えできる。数値列なら-n、区切り変更は-tを併用する。
空白区切りや CSV のデータでは、-k を使います。何列目で並べ替えるか を指定できます。
$ cat sales.txt
apple 120 banana 80 cherry 200 date 50
# 2 列目(数値)で降順に並べ替える $ sort -k2 -nr sales.txt
cherry 200 apple 120 banana 80 date 50
-k2で 2 列目を基準にします- 数値の列なら
-nを忘れずに付けます - 区切り文字を変えたいときは
-t,(カンマ区切り)のように書きます
7. よくある初心者のつまずき
結論: 重複が消えないのは
sort忘れ、数字が変なのは-n忘れが原因。自分自身への上書きは厳禁。
7-1. uniq を使ったのに重複が消えない
原因:sort をしていません。
# NG: 連続していない重複は消えない $ uniq fruits.txt # OK $ sort fruits.txt | uniq $ sort -u fruits.txt
7-2. 数字が変な順に並ぶ
原因:-n を付けていません。文字列としての比較になっています。
$ sort -n scores.txt # 数値として並べる
7-3. 元ファイルが書き換わらない
sort は 画面に結果を出すだけ です。元ファイルは変わりません。書きかえたいときは 自分でリダイレクトします。
$ sort fruits.txt > fruits-sorted.txt
やってはいけないこと
# NG: ファイルが空になる $ sort fruits.txt > fruits.txt
> は コマンドを実行する前にファイルを空にします。そのため sort が読む前に中身が消えます。GUI の「上書き保存」とは動きがちがう点に注意してください。
同じファイルに書き戻したいときは、別ファイルに出してから差しかえます。または sort -o を使います。
# OK: -o は読み終わってから書き込む $ sort -o fruits.txt fruits.txt
本サイトの仮想ターミナル入力したコマンドを解釈してコンピュータに実行させる対話プログラム。は学習用です。あなたのパソコンのファイルは壊れません。安心して試してください。
7-4. 大文字・小文字が別物扱いされる
$ cat names.txt
Alice bob Alice BOB
$ LC_ALL=C sort -u names.txt
Alice BOB bob
LC_ALL=C を付けたのは、並び順をこの記事と同じにそろえるためです。付けないと、ロケールによっては bob が BOB より先に来ます。
大文字と小文字を区別したくないときは -f(fold case)を付けます。
$ LC_ALL=C sort -uf names.txt
Alice bob
8. ミニ課題:実際にやってみよう
結論: ユニーク化・出現回数集計・降順ランキングの 3 問で、
sortとuniqの連携を手で確かめる。
課題 1:次のファイルからユニークな単語の一覧を出そう。
$ cat << 'EOF' > words.txt apple banana apple cherry banana EOF
ヒント 1(方向づけ)を見る
「並べ替え」と「重複削除」を 1 回でやってくれるオプションがありました。第 3 章を思い出してください。
ヒント 2(コマンド名)を見る
使うのは sort です。並べ替えと重複削除を同時にやるオプションが 1 つあります。sort --help で探してみてください。
答えを見る
$ sort -u words.txt
apple banana cherry
課題 2:上のファイルから 各単語が何回出たか を集計しよう。
ヒント 1(方向づけ)を見る
数える前に、同じ単語をとなり合わせに集める必要があります。つまり 2 段のパイプになります。
ヒント 2(コマンド名)を見る
使うのは sort と uniq です。uniq には回数を数えるオプションがあります。
答えを見る
$ sort words.txt | uniq -c
2 apple
2 banana
1 cherry
課題 3:上の集計結果を 多い順(降順) に並べ替えて、上位 2 件だけ表示しよう。
ヒント 1(方向づけ)を見る
カウントの列は数字です。数として大きい順に並べ直します。そのあと先頭から 2 件だけ取り出します。
ヒント 2(コマンド名)を見る
使うのは sort と head です。sort には数値として見るオプションと、逆順にするオプションがあります。
答えを見る
$ sort words.txt | uniq -c | sort -rn | head -n 2
2 banana
2 apple
apple と banana はどちらも 2 回で同じ数です。回数が同じときは、行全体を見くらべた結果で並びます。-r が付いているので逆順になり、banana が先に来ます。
9. コピペ用テンプレート
結論: 並べ替え・重複削除・頻度ランキング・列指定・安全な上書きのよく使う型を手元に置いておく。
よく使う型をまとめておく
# 並べ替え(辞書順) sort file.txt # 並べ替え+重複削除 sort -u file.txt # 数値として並べ替え(昇順 / 降順) sort -n file.txt sort -nr file.txt # 重複行のカウント sort file.txt | uniq -c # 頻度ランキング(多い順) sort file.txt | uniq -c | sort -rn # 頻度ランキング上位 10 件 sort file.txt | uniq -c | sort -rn | head -n 10 # 2 列目で降順 sort -k2 -nr file.txt # 大文字小文字を無視してユニーク化 sort -uf file.txt # 元ファイルにそのまま書き戻す(事故防止: -o を使う) sort -o file.txt file.txt
10. 振り返り
uniq はとなり合った行しか見ないから、先に sort で集めておくんですね。-n。付け忘れると文字として比べられてしまう。ここも大丈夫です。sort file > file をしないこと。中身が消えてしまうからね。今日の 3 行まとめ
uniqはとなり合った重複しか削らない。だから先にsortで同じ行を集める- 数字を並べるときは
-nを付ける。付けないと文字として比べられる - 頻度ランキングは
sort | uniq -c | sort -rnの 3 段パイプ