この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。GNU Coreutilsのsort・uniq・comm公式仕様を参照し、架空の端末名一覧の比較を説明します。検証ステータス:📘 公式仕様確認済み・掲載コマンドの実機実行は未確認
Linuxのuniqで重複が消えない?sortとcommで一覧差分を安全に調べる
端末一覧から重複を取り除こうとして uniq を使ったのに、同じ名前が残ることがあります。これは故障ではありません。uniq が比較するのは隣り合った行だけだからです。順番がばらばらな一覧なら、先に sort で並べ替える必要があります。一方、変更前後の二つの一覧を比べるときは、comm を使うと追加・削除・共通を区別できます。
この違いは、端末台帳、配布先、許可リスト、設定項目の確認で役立ちます。ただし「重複を消す」と「変更を調べる」は別の仕事です。片方だけを覚えて運用に使うと、削除された項目を見落とすことがあります。この記事では、架空の名前だけを使って安全に観察します。
対象環境と確認範囲
| 項目 | 内容 |
|---|---|
| 対象 | GNU Coreutilsのsort、uniq、commを利用できるLinux |
| 操作 | 文字列を標準入力から渡す読み取り中心の例 |
| 権限 | 管理者権限は不要 |
| 対象データ | 架空の端末名のみ。実際の端末台帳は変更しない |
| 検証 | GNU公式仕様を参照。掲載コマンドの実機実行は未実施 |
Ubuntuなどではこれらが標準的に利用できますが、BusyBoxやBSD系の実装ではオプションや細部が異なることがあります。この記事の説明はGNU版を前提にします。実行前に sort --version などで実装を確かめ、環境が違えばその環境のマニュアルを確認してください。
最初の実験:同じ行なのに残る
まずファイルを作らず、シェルから架空の端末名を渡します。次のコードは対話シェルを終了したり、サービスを変更したりしません。
printf '%s\n' pc-a pc-b pc-a pc-c | uniq
GNU版の仕様から期待される出力は pc-a、pc-b、pc-a、pc-c の4行です。最初と3行目の pc-a の間には pc-b があり、隣接していません。そのため uniq はどちらも残します。ここで観察すべきなのは、同じ文字列があるかどうかではなく、直前の行と一致しているかという判定条件です。
次は、途中に並べ替えを加えます。これは元の入力順を保持しません。並び順が意味を持つログや作業手順には、そのまま適用しないでください。
printf '%s\n' pc-a pc-b pc-a pc-c | LC_ALL=C sort | uniq
期待される出力は pc-a、pc-b、pc-c の3行です。並べ替えによって二つの pc-a が隣り合い、uniq が一つにまとめられます。なお sort -u も重複をまとめる選択肢ですが、キー指定や照合規則を使う場合は単純な全行一致と同じ意味になるとは限りません。まずは全行を比較する小さな例から始めましょう。
なぜsortを先に使うのか
次の図は、入力順がばらばらな一覧を重複なしの集合へ変える処理を表しています。図の目的は、uniq が全体を記憶して重複探索しているのではなく、隣接比較を行うことを示す点にあります。
flowchart TD
A["入力: a, b, a, c"] --> B["sort: a, a, b, c"]
B --> C["uniq: 隣接する同じ行をまとめる"]
C --> D["出力: a, b, c"]
入力の段階では二つの a が離れています。sort の後では隣接するため、uniq が同じ行をまとめられます。この処理は、値が一意であるかの点検には向きますが、元の出現位置や時系列を復元できません。監査用に元データを保持したい場合は、原本を残したまま別の集計結果として出力してください。
LC_ALL=C は、比較時のロケール差を減らすために例で指定しています。英数字の端末名では扱いやすい一方、日本語の人名や自然言語を読みやすい順番に並べたい用途では適切とは限りません。ロケールは文字の並び方だけでなく、同一と見なす比較の条件にも影響し得るため、二つの一覧で同じ条件を使うことが大切です。
重複の件数を数える場合
重複を削除する前に、何件あるのか調べたいこともあります。たとえば端末名が二度記載されているなら、単なる入力ミスなのか、別の部門が同じ名前を使っているのか、元の台帳へ戻って確認したいでしょう。uniq -c は連続する同じ行の件数を先頭に付けます。
printf '%s\n' pc-a pc-b pc-a pc-c | LC_ALL=C sort | uniq -c
期待値は pc-a が2、pc-b と pc-c が各1です。件数の前には空白が入るため、機械処理で使う場合に表示幅を固定値で切り出す設計は避けてください。また、この件数は「入力された行数」であって、「実際に存在する物理端末の台数」ではありません。同じ端末が複数の記録に現れるなら、台数として数える前に識別子の意味を確かめる必要があります。
変更前と変更後を比べる:commの3列
次は、変更前の端末一覧が pc-a、pc-b、pc-c、変更後が pc-b、pc-c、pc-d だったとします。知りたいのは重複数ではなく、消えた名前と増えた名前です。この場合は二つの入力を比較する comm が適しています。
comm <(printf '%s\n' pc-a pc-b pc-c | LC_ALL=C sort) <(printf '%s\n' pc-b pc-c pc-d | LC_ALL=C sort)
この例の <(...) はBashのプロセス置換です。POSIXのすべてのシェルで使えるわけではありません。Bash環境で試してください。期待される表示では、1列目に変更前だけの pc-a、2列目に変更後だけの pc-d、3列目に共通の pc-b と pc-c が出ます。列は通常タブで区切られます。画面の幅や貼り付け先によって列位置が見えにくいことがあります。
comm は入力がそれぞれ比較規則に従ってソート済みであることを前提にします。片方だけ並べ替えてもう片方をそのまま渡すと、比較の前提が崩れます。実務で比較する際は、双方に同じ LC_ALL と並べ替え条件を適用してください。名前の大文字・小文字を同一視するかも、比較前に業務ルールとして決める必要があります。
1条件を変える:追加だけを取り出す
追加された端末だけを知りたいなら、comm -13 を使います。1列目と3列目を隠すため、変更後にしかない項目が残ります。これは「変更後に存在する全端末」を表示するのではなく、前回の一覧から増えた項目を取り出す操作です。
comm -13 <(printf '%s\n' pc-a pc-b pc-c | LC_ALL=C sort) <(printf '%s\n' pc-b pc-c pc-d | LC_ALL=C sort)
期待される結果は pc-d の1行です。反対に comm -23 は変更前だけの項目を表示し、期待結果は pc-a です。削除候補を調べるときは、消えた項目をそのまま削除命令へ渡さないでください。収集漏れや一時的な接続不良でも一覧から名前が消えることがあるため、取得条件と前回時点の整合性を先に確認します。
さらに comm は「同じ名前が何回出たか」も比較へ影響し得ます。端末IDを一意な集合として扱うなら、比較前にそれぞれ sort -u で正規化する設計を検討します。一方、発注数やイベント回数など、重複そのものが意味を持つデータでは、一意化すると重要な情報を失います。目的を決めずに重複除去を組み込まないことが重要です。
期待どおりにならない場合の切り分け
まず、末尾の空白、先頭の空白、改行コード、大文字小文字を確認します。pc-a と pc-a は見た目が似ていても別の行です。pc-A と pc-a も、比較条件によって同じ扱いになるとは限りません。実データを公開画面へ貼る代わりに、機密値を伏せた検証用コピーで差を観察してください。
次に、一覧が同じ時点・同じ範囲から取得されたかを確認します。前回は全拠点、今回は一部拠点だけという状態で比較すると、実際には削除されていない端末が「消えた」ように見えます。名前だけの比較では同名の別端末を識別できないこともあります。資産番号など一意なキーがあるなら、比較対象の設計を見直します。
最後に、入力の生成処理が失敗していないかを確認します。空の一覧を comm に渡すと、大量の追加・削除として解釈されかねません。運用の自動化では、取得処理の終了状態、入力件数、収集時刻、対象範囲を確認してから差分を評価してください。コマンドが正常終了したことだけでは、入力が正しかった証拠になりません。
業務ではどのコマンドを選ぶか
| 確認したいこと | 選択肢 | 注意点 | |
|---|---|---|---|
| 一覧の重複を除いた名前 | sort -u | 元の並び順を失う | |
| 同じ名前が何件あるか | `sort | uniq -c` | 行数と実物の数は別 |
| 変更前後の追加・削除 | comm | 両入力のソート条件をそろえる | |
| 行の並び順まで含む変更 | diff | 集合としての差分とは意味が違う |
たとえば端末台帳の毎月の照合なら、まず両方の収集条件と件数を記録し、端末IDを正規化してから差分を表示します。差分が出たら担当者が元の台帳や管理システムを確認し、追加・廃止・収集漏れを区別します。比較結果をそのまま権限削除や機器停止に結び付けない設計が安全です。
diff は行の順序も含めたテキストの違いを確認する用途に向いています。一方 comm は、ソート済みの二つの行集合を「前だけ・後だけ・共通」に分類する用途に向きます。二つは優劣ではなく問いの違いです。順序の変更を問題にする設定ファイルと、端末名の追加削除を知りたい台帳では、適した道具が異なります。
まとめ
uniq は隣接した同じ行をまとめる道具です。離れた重複を探すなら、比較規則をそろえて sort を先に使います。件数を知りたいなら uniq -c、変更前後の追加・削除を知りたいなら comm を使い分けます。実務では、ソート条件と入力の取得範囲を固定し、差分を人が確認してから変更操作へ進むことが重要です。
