テキスト比較
2つのテキストの追加・削除・変更行を一目で比較
比較結果
両方のテキストを入力して比較ボタンを押してください。
処理中…
0.0
停止していません。計算が終わると結果が表示されます。
テキスト比較について
このツールは2つのテキストを行に分け、両方に共通して残せる行をできるだけ多く選ぶLCS(最長共通部分列)方式で比較します。共通の行はそのまま、左だけにある行は削除(-)、右だけにある行は追加(+)として表示します。行の中のどの文字が変わったかは表示しません。
diffの結果が「自分が直した内容」と違って見えることはよくあります。アルゴリズムが探すのは編集の意図ではなく、「変更行数がいちばん少ない説明」だからです。
diffは最小の編集を探すだけ
差分を求める問題は、「AをBに変える最短の挿入・削除リスト」を探す問題です。1976年のUnix diffはHunt–McIlroyのアルゴリズムを使い、1986年にEugene Myersが論文「An O(ND) Difference Algorithm and Its Variations」で、差分が小さいほど速く終わる方法を発表しました。Nは2つの入力の長さの合計、Dは最小の編集数です。Gitの標準のdiffはこのMyersのアルゴリズムです。
このツールもMyersのアルゴリズムを使います。問題を半分ずつに分けて解く線形空間版なので、メモリは行数に比例し、2つの文章が似ているほど速く終わります。2万行どうしで1%が違う場合でも1秒かかりません。ただし、まったく違う文章のように差分が大きい入力では時間が差分に比例して増え、数万行だと数秒かかることがあります。編集数は常に最小ですが、最小解が複数あるときはGitと違う解を選ぶことがあり、変更ブロックの中では削除を先に表示します。
diffが「間違って」見える典型
既存のブロックのすぐ上に似たブロックを追加すると、閉じかっこ } の組み合わせがずれて、新しいブロックの終わりと古いブロックの始まりが混ざったように表示されます。間違いではなく、同じ長さの説明が複数あってその1つを選んだ結果です。Gitに --diff-algorithm=patience や histogram があるのはこのためで、一度しか出てこない行を先に目印にすることで、人が見て自然な結果になりやすくなります。
行の順番を入れ替えただけでも、diffには「移動」という概念がないので、削除と追加として表示されます。
1行のうち1文字だけ直しても、行全体が削除1+追加1になります。日本語の原稿は1段落が1行になりがちで、ほぼすべての修正がこう見えます。句点ごとに改行してから比べると、ずっと読みやすくなります。
目に見えない違い
同じに見える行が違うと出たら、見えない文字を疑ってください。ノーブレークスペース(U+00A0)は普通の半角スペースとは別の文字です。全角スペース(U+3000)と半角スペースの違いも画面では気づきにくい差です。「前後の空白を無視」は各行の両端を削ってから比べます(JavaScriptのtrimはU+00A0もU+3000も空白として扱います)。行の途中にある文字はそのままです。
改行コードの違い(WindowsのCRLFとmacOS・LinuxのLF)は、比較前にすべてLFにそろえるので差分になりません。
- 大文字小文字を無視: 比較時だけ小文字にし、表示は元のままです。
- 空行を無視: 両側から空行(空白だけの行を含む)を除いて比べます。行番号は元の番号のままです。
- 最後の行のあとに改行が1つ多いと、空行1行の追加として出ます。
例
ブロックを直して新しいブロックを追加した
- 入力
左: if (a) { x(); } 右: if (a) { y(); } if (b) { x(); }- 結果
if (a) { + y(); + } + if (b) { x(); } (追加3、削除0、同一3)
人の意図どおりに説明すると削除1+追加4で5行ですが、アルゴリズムは3行追加だけのより短い説明を選びます。
同じに見えるのに違うと出る
- 入力
左: a[NBSP]b 右: a b- 結果
- a b + a b (追加1、削除1)
真ん中の空白がU+00A0とU+0020で異なります。
CRLFとLF
- 入力
左: line1\r\nline2 右: line1\nline2- 結果
line1 line2 (同一2)
改行コードをそろえてから比べるので、差はありません。
使い方
- 左に元の文章、右に修正後の文章を貼り付けます。
- 必要なら大文字小文字・前後の空白・空行を無視するオプションをオンにします。
- 緑(追加)と赤(削除)の行を確認し、必要なら結果をコピーします。
よくある質問
1文字直しただけなのに行全体が変わったと出ます。
行単位で比較しているためです。長い段落は文ごとに改行してから比べてください。
Gitのdiffと結果が違います。
最小解が複数あるときの選び方が違うためです。またこのツールはCRLFとLFを同じとみなします。
コピーした結果をpatchに使えますか?
使えます。「unified diffをコピー」は、ファイルヘッダ(--- a/text.txt、+++ b/text.txt)、@@ -開始,行数 +開始,行数 @@ ヘッダ、前後3行の文脈を含む標準形式なので、元のファイルにpatch -p1やgit applyで適用できます。ファイル名だけ実際の名前に書き換えてください。正確に適用できるよう、大文字小文字・空白・空行を無視するオプションに関係なく、文字どおりに比較して作ります。
全角と半角の違いも検出されますか?
はい、別の文字なので違いとして出ます。大文字小文字の無視オプションも全角・半角はそろえません。
出典
- Myers, E. W. (1986). An O(ND) Difference Algorithm and Its Variations. Algorithmica 1
- Git documentation — git diff (--diff-algorithm)
- MDN — String.prototype.trim
基準日: