差分比較(diff)って、こういう時に荒れる。
- 行の順番が違うだけで全部差分に見える
- 同じ行が何度も出てきて、差分が汚れる
- 「結局、存在する行の集合は同じ?」を見たいだけなのに、順序が邪魔
そんな時に効くのが 行のユニーク化。
つまり、テキストを「同一行の集合」にしてから比較する。
やることはこれだけ。
- 行を ソート
- 行を 重複排除(Unique)
- 必要なら 空行や行末空白も調整
これで diff は一気に読みやすくなる。
どんな時に使う?
- 設定ファイルの値一覧を比較したい
- 抽出したURL一覧、ホスト名一覧を比較したい
- ログから拾った“エラー行一覧”の比較
- 2つのファイルが「同じ要素を含むか」を確認したい(順序は不要)
方式(何を揃えるか)
“集合化”するなら、よくある揃え方は次の3つ。
A) そのまま集合化(最小)
- ソート + 重複排除
- 行末空白とか大小文字はそのまま
B) 大文字小文字を無視して集合化
ABCとabcを同じ扱いにして比較したい時
C) 行末空白を消して集合化(おすすめ)
- 見えない空白のせいで「別行」扱いになる事故を防ぐ
この記事の手順は、A/B/Cの切り替えができる形にする。
用意するもの(2ファイル)
- PowerShell フィルタ:
filters\hm_setify.ps1 - 秀丸マクロ:
line_setify.mac
外部コマンド連携(runex)で、選択(または全文)をフィルタへ渡して戻す方式。
1) PowerShell フィルタ(集合化の本体)
ファイル名:filters\hm_setify.ps1
param(
[switch]$IgnoreCase,
[switch]$TrimRight,
[switch]$DropBlank
)
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$text = [Console]::In.ReadToEnd()
$lines = $text -split "`r?`n"
if ($TrimRight) {
$lines = $lines | ForEach-Object { $_ -replace "[ \t]+$", "" }
}
if ($DropBlank) {
$lines = $lines | Where-Object { $_ -ne "" }
}
# Sort-Object -Unique で集合化(順序は捨てる)
if ($IgnoreCase) {
# 大文字小文字無視:ToLowerInvariantでキー化して保持(元行はそのままだとブレるので小文字側で統一)
$items = foreach ($l in $lines) {
[PSCustomObject]@{ raw=$l; key=$l.ToLowerInvariant() }
}
$out = $items |
Sort-Object key -Unique |
ForEach-Object { $_.key } # 比較を安定させるため小文字で統一して出す
} else {
$out = $lines | Sort-Object -Unique
}
$out -join "`r`n"
2) 秀丸マクロ(選択→集合化→戻す)
ファイル名:line_setify.mac
/*
line_setify.mac
行の集合化(ソート + 重複排除)を行う。
- 目的:差分比較の前処理
*/
#ic = val(input("大文字小文字無視: 0=しない / 1=する", "0"));
#trim = val(input("行末空白を削除: 0=しない / 1=する(推奨)", "1"));
#blank= val(input("空行を捨てる: 0=残す / 1=捨てる", "1"));
if (!selecting) {
selectall;
}
$ps = "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"" + macrodir + "\\filters\\hm_setify.ps1\"";
if (#ic == 1) { $ps = $ps + " -IgnoreCase"; }
if (#trim == 1) { $ps = $ps + " -TrimRight"; }
if (#blank == 1){ $ps = $ps + " -DropBlank"; }
// runex:選択→stdin、stdoutで置換
runex $ps
, 1
, 5, ""
, 6, ""
, 7, ""
, 1, ""
, 0
, 1
, 6 // UTF-8
, 1
;
if (!result) {
message "失敗。filters\\hm_setify.ps1 の場所とPowerShell実行を確認。";
endmacro;
}
message "行の集合化 完了";
導入手順(3分)
- マクロ置き場に
filtersフォルダを作る filters\hm_setify.ps1を保存line_setify.macを保存- 秀丸で マクロ登録(
line_setify.mac) - 必要ならキー割り当て
使い方(差分比較の定番手順)
手順1:2つのファイルをそれぞれ集合化する
- ファイルAを開く → マクロ実行 → 集合化
- 別名保存(例:
A.set.txt) - ファイルBも同じ → 別名保存(例:
B.set.txt)
手順2:集合化したファイル同士をdiffする
A.set.txtとB.set.txtを比較する
これで「順番が違うだけ」のノイズは消えて、
本当に差がある行だけが見える。
実例(イメージ)
元のテキスト(順序バラバラ+重複あり)
A:
cat
dog
cat
bird
B:
dog
bird
cat
集合化後(順序を捨てた同一行の集合)
A.set / B.set:
bird
cat
dog
diffすると差分はゼロ。
「含んでいる行の集合は同じ」ってことが一発で分かる。
注意点(ここだけ読めばOK)
- 集合化は 順序を捨てる。ログの時系列みたいに順序が重要なら向かない
- 大文字小文字無視をONにすると、出力は小文字に統一される(比較を安定させるため)
- 行末空白は見えない差分の原因になりやすいので、基本は削除ONが無難
- いきなり上書きしたくないなら、必ず別名保存してから比較する
まとめ
差分比較で「順番違い」がノイズになるなら、先に“集合化”する。
ソート+重複排除で、比較対象がスッキリして差分が読みやすくなる。
やることは単純だが、効果はデカい。
