sort と uniq の使い方 - データを並べ替えて重複を削る

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 行ずつ並べ替えて表示 してくれる。
ライニー先輩: 大事なのは、中身を書きかえるわけではないという点。並べ替えた結果を画面に出すだけなんだ。だから打ちまちがえても、元のファイルは壊れないよ。
リナ: 元ファイルにはさわらないんですね。それなら安心です。
ライニー先輩: そう。並べ替えには 辞書順・数値順・逆順 の 3 種類がある。これだけ覚えれば 8 割は対応できるよ。

サンプルとして次のファイルを用意しよう。

$ 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

-rreverse(逆)の頭文字です。

2. 数値の並べ替えで初心者がハマる罠

結論: sort のデフォルトは文字列比較。数値として正しく並べたいときは -n を付ける。

リナ: 数字を並べ替えたら、順番が変になりました。
ライニー先輩: ちょうどいい例だね。実際に見てみよう。
$ cat scores.txt
100
3
25
9
1000
$ sort scores.txt
100
1000
25
3
9
リナ: えっ、10025 より先に来ています。39 は最後です。これはバグですか。
ライニー先輩: バグではないよ。sort は、はじめの設定では 文字列として 1 文字ずつ左から見くらべる
ライニー先輩: つまり最初の 1 文字だけで見ると、123 より小さい。だから 1001000 が前に来るんだ。
リナ: なるほど、数として見ていなかったんですね。びっくりしました。
ライニー先輩: 数として並べたいときは -n を付ける。それだけで直るよ。

2-1. 数値ソート -n

$ sort -n scores.txt
3
9
25
100
1000

-nnumeric(数値)の頭文字です。

初心者あるある

  • ログのサイズや件数を並べるとき、-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
リナ: あれ、applebanana が 1 行ずつになりました。
ライニー先輩: そう。-uunique(一意)の頭文字だよ。sort の結果から重複した行を取りのぞいてくれる。
ライニー先輩: 「並べ替えてユニークにしたい」だけなら、これ 1 つで済む んだ。

実務では「ユニークな値の一覧が欲しい」場面がとても多いです。sort -u を覚えておくと早く書けます。

4. uniq:重複を削る専門コマンド

結論: uniq は連続した重複しか削れない。必ず sort の後ろに置く。-c で出現回数を数えられる。

4-1. リナの失敗:uniq だけでは消えない

$ uniq fruits.txt
banana
apple
cherry
apple
banana
date
リナ: あれっ、applebanana もまだ重複しています。コマンドが効いていないのでしょうか。
ライニー先輩: 効いてはいるよ。ただし 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

-ccount(数える)の頭文字です。行の先頭に 出現回数 が付きます。集計にとても便利です。

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 件に絞れる。

リナ: アクセスログで「どの IP からのアクセスが多いか」を出したいです。どうすればいいですか。
ライニー先輩: それが今日のクライマックスだよ。sort | uniq -c | sort -rn という 3 段パイプ が定番。
ライニー先輩: この形は丸暗記していい。なぜ 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 を付けたのは、並び順をこの記事と同じにそろえるためです。付けないと、ロケールによっては bobBOB より先に来ます。

大文字と小文字を区別したくないときは -ffold case)を付けます。

$ LC_ALL=C sort -uf names.txt
Alice
bob

8. ミニ課題:実際にやってみよう

結論: ユニーク化・出現回数集計・降順ランキングの 3 問で、sortuniq の連携を手で確かめる。

リナ: 知識は入りました。手を動かして確かめたいです。
ライニー先輩: いいね、3 問用意したよ。ターミナルで試してみて。

課題 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(コマンド名)を見る

使うのは sortuniq です。uniq には回数を数えるオプションがあります。

答えを見る
$ sort words.txt | uniq -c
      2 apple
      2 banana
      1 cherry

課題 3:上の集計結果を 多い順(降順) に並べ替えて、上位 2 件だけ表示しよう。

ヒント 1(方向づけ)を見る

カウントの列は数字です。数として大きい順に並べ直します。そのあと先頭から 2 件だけ取り出します。

ヒント 2(コマンド名)を見る

使うのは sorthead です。sort には数値として見るオプションと、逆順にするオプションがあります。

答えを見る
$ sort words.txt | uniq -c | sort -rn | head -n 2
      2 banana
      2 apple

applebanana はどちらも 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 行まとめ

  1. uniq はとなり合った重複しか削らない。だから先に sort で同じ行を集める
  2. 数字を並べるときは -n を付ける。付けないと文字として比べられる
  3. 頻度ランキングは sort | uniq -c | sort -rn の 3 段パイプ

まとめ:次に読む

この記事を共有