Diff(差分比較)ツール
2つのテキストを比較して、変更・追加・削除箇所をハイライト表示します。
比較したい2つのテキストを入力してください。プログラミングコード、設定ファイル、文章の校正など、あらゆるテキストの差異を瞬時に抽出します。
Diff(差分比較)ツールの使い方
2 つのテキストを比較し、削除された箇所を赤、追加された箇所を緑でハイライトします。差分計算には Myers のアルゴリズムを実装した JavaScript ライブラリ jsdiff(npm の diff パッケージ)を使い、行単位(diffLines)と文字単位(diffChars)を切り替えられます。プログラムコードの修正確認、文章の校正前後の比較、設定ファイルの変更点の洗い出しなどに使え、入力のたびにブラウザ内で再計算されるため、テキストがサーバーへ送信されることはありません。
テキストの入力
左の「比較元(旧)」に変更前、右の「比較先(新)」に変更後のテキストを貼り付けます。入力のたびに差分が再計算され、下の「比較結果」に表示されます。「サンプルを読み込み」で動作を試せます。
比較設定の選択
「行単位」は改行で区切った 1 行を最小単位として比較し、「文字単位」は 1 文字ずつ比較します。表示形式は「左右並列」(旧を左・新を右に分けて表示)と「インライン」(1 つの流れの中に削除と追加を混在表示)から選べます。
差分の確認
赤い背景は削除、緑の背景は追加、通常の色は共通部分です。インライン表示では削除箇所に取り消し線が付きます。行単位モードでは、行の一部だけが変わった場合でも行全体が「削除+追加」として表示されます。
行 diff と文字 diff の違いとアルゴリズム
このツールは jsdiff の diffLines(行単位)と diffChars(文字単位)を呼び分けています。どちらも Myers のアルゴリズムで「最小の編集手順」を求めますが、最小単位(トークン)が違うため、同じ入力でも結果の見え方が大きく変わります。
| 項目 | 行単位(diffLines) | 文字単位(diffChars) |
|---|---|---|
| 最小単位 | 改行文字までを含む 1 行 | 1 文字(絵文字などのサロゲートペアは 1 文字) |
| 行の一部だけ変えた場合 | 行全体が削除+追加 | 変わった文字だけが削除+追加 |
| 空白・改行コードの扱い | 区別する(ignoreWhitespace / stripTrailingCr は未使用) | 区別する(空白も改行も 1 文字として比較) |
| 向いている用途 | ソースコード・設定ファイル・CSV など行構造のあるテキスト | 文章の校正・短い文字列の比較 |
| 計算量の目安 | O(ND)。N は行数の和、D は変更行数 | O(ND)。N は文字数の和、D は変更文字数。長文で差分が多いと重い |
Myers のアルゴリズムは、2 つのトークン列を「削除」「追加」「一致」の 3 種類の操作に分解し、削除と追加の合計回数 D が最小になる経路を探索します。 計算量は O(ND) なので、テキストが長くても差分が少なければ高速に終わり、逆に短いテキストでも内容がほぼ別物だと探索範囲が広がります。 このツールは結果を「削除」「追加」「共通」の断片の配列として受け取り、それぞれ赤・緑・通常色の <span> として描画しています。
出典:E. Myers, “An O(ND) Difference Algorithm and Its Variations” (1986)、jsdiff(GitHub)
git diff の表記とこのツールの表示の対応
git diff に慣れている方向けに、unified diff 形式の各表記がこのツールのどの表示に対応するか、また git にあってこのツールに無い機能を整理しました。
| git diff の表記 | 意味 | このツールでの表示 |
|---|---|---|
| - で始まる行 | 旧側にだけある行(削除) | 赤い背景。インライン表示では取り消し線付き |
| + で始まる行 | 新側にだけある行(追加) | 緑の背景 |
| 空白で始まる行 | 両方に共通する文脈行 | 通常の色。git と違い、変更の無い部分も省略せず全文を表示 |
| @@ -1,4 +1,4 @@ | ハンク(変更のまとまり)の行番号範囲 | 相当する表示なし。行番号は表示されません |
| \ No newline at end of file | 末尾改行の有無が異なる | 最終行が削除+追加として表示される |
| --word-diff | 行内の単語単位で差分表示 | 「文字単位」モードが近い(単語ではなく文字が単位) |
| -w / --ignore-all-space | 空白の違いを無視 | 相当する機能なし(空白は常に区別) |
| --ignore-cr-at-eol | 行末の CR を無視 | 相当する機能なし(CRLF と LF は別扱い) |
git diff のオプションの一次情報はgit-diff のリファレンスを参照してください。このツールは 2 つのテキストを直接比較する用途に絞っており、パッチファイル(.diff / .patch)の生成や読み込みには対応していません。
実際の使用例
サンプルテキストを行単位で比較
「サンプルを読み込み」ボタンで入る 4 行ずつのテキストを行単位で比較した結果です。1 行目は句点が「。」から「!」に変わっただけですが、行単位では行全体が削除+追加になります。2 行目は共通、3〜4 行目はまとめて 2 行削除・2 行追加として扱われます。
INPUT
【旧】 こんにちは。 これはサンプルのテキストです。 修正前の内容が含まれています。 この行は削除されます。 【新】 こんにちは! これはサンプルのテキストです。 修正後の内容に変更されました。 新しい行が追加されました。
OUTPUT
[削除] こんにちは。 [追加] こんにちは! [共通] これはサンプルのテキストです。 [削除] 修正前の内容が含まれています。 [削除] この行は削除されます。 [追加] 修正後の内容に変更されました。 [追加] 新しい行が追加されました。
文章の推敲を文字単位で比較
漢数字を算用数字に、句点を感嘆符に変えた例です。文字単位では変わった文字だけがピンポイントでハイライトされ、共通部分はそのまま表示されます。
INPUT
【旧】昨日はとても楽しい一日でした。 【新】昨日はとても楽しい1日でした!
OUTPUT
[共通] 昨日はとても楽しい [削除] 一 [追加] 1 [共通] 日でした [削除] 。 [追加] !
プログラムの修正確認(行単位)
関数に引数を追加し、ログ出力を変更した例です。変更のあった 1〜2 行目が削除+追加、閉じ括弧の 3 行目だけが共通として表示されます。
INPUT
【旧】
function greet(name) {
console.log("Hello " + name);
}
【新】
function greet(name, greeting = "Hello") {
console.log(greeting + " " + name);
}OUTPUT
[削除] function greet(name) {
[削除] console.log("Hello " + name);
[追加] function greet(name, greeting = "Hello") {
[追加] console.log(greeting + " " + name);
[共通] }よくある質問
行単位と文字単位はどう使い分ければよいですか?
行単位(diffLines)は改行までの 1 行を最小単位とするため、1 文字でも違えば行全体が削除と追加のペアとして表示されます。どの行が変わったかを素早く把握したいコードや設定ファイルの比較に向いています。文字単位(diffChars)は 1 文字を最小単位とし、句読点や助詞の変更など行の中のどこが変わったかまで特定できるので、文章の校正に向いています。ただし文字単位は比較対象が長く差分が多いほど計算量が増えるため、まず行単位で変更箇所を絞り、必要な部分だけを文字単位で見るのが効率的です。
改行コード(CRLF と LF)が違うだけでも差分として表示されますか?
表示されます。行単位モードでは「abc\r\n」と「abc\n」は別のトークンとして扱われ、内容が同じに見える行がすべて削除+追加としてハイライトされます。\r(CR)は画面上に表示されないため、見た目が同じ行が全行ハイライトされたときは改行コードの違いを疑ってください。Windows のメモ帳などで保存したファイルは CRLF になっていることがあります。jsdiff には CR を無視する stripTrailingCr オプションがありますが、このツールでは既定値(false)のまま使用しているため、比較前に改行コードをそろえる必要があります。
行末の空白やタブ、全角スペースは区別されますか?
区別されます。このツールは jsdiff の ignoreWhitespace オプションを指定していない(既定 false)ため、「foo 」(末尾に半角スペース)と「foo」は異なる行として扱われます。タブとスペース、半角スペースと全角スペースも別の文字です。さらに、テキスト末尾の改行の有無も区別され、最終行が「b」のテキストと「b\n」のテキストを比べると最終行が削除+追加として表示されます(ignoreNewlineAtEof も未使用)。エディタの「末尾の空白を削除」機能などで整えてから比較すると、意図しない差分を減らせます。
大量のテキストでも比較できますか?
数千行程度であれば実用的に動作します。jsdiff が実装する Myers のアルゴリズムは計算量が O(ND)(N は 2 つのテキストの長さの和、D は差分の大きさ)で、テキストが長くかつ差分が多いほど時間がかかります。特に、内容がほとんど異なる長文同士を文字単位で比較すると重くなります。このツールは jsdiff の maxEditLength や timeout による打ち切りを設定していないため、計算が終わるまでブラウザのタブが応答しなくなることがあります。巨大なファイルは分割するか、行単位モードを使ってください。
絵文字や結合文字は正しく 1 文字として扱われますか?
このサイトが使用している jsdiff 8 系の diffChars は、サロゲートペアで表現される絵文字を 1 文字として扱います。たとえば「a😀b」と「a😃b」を比べると、😀 の削除と 😃 の追加として表示され、絵文字の途中で分割されることはありません。一方、Unicode の正規化は行わないため、NFC 形式の「が」(1 文字)と NFD 形式の「か」+濁点(2 文字)は別の文字列として扱われます。macOS で作成したファイル名や一部のコピー元では NFD になっていることがあるため、見た目が同じなのに差分が出る場合は正規化形式の違いを確認してください。
左右並列表示で左右の行位置がずれて見えるのはなぜですか?
左右並列表示は、左側に「追加以外」の断片、右側に「削除以外」の断片を上から順に並べているだけで、行番号による整列や空行の挿入は行っていません。そのため、削除された行数と追加された行数が異なる箇所では、それ以降の行の上下位置が左右でずれます。対応関係を 1 か所ずつ追いたい場合はインライン表示に切り替えると、削除(取り消し線付き)と追加が同じ位置に並んで表示されます。
入力したデータは保存・送信されますか?
いいえ。入力テキストは React の state に保持され、差分計算はブラウザ内で jsdiff を呼び出して行います。サーバーへの送信や localStorage への保存は行っていないため、ページを再読み込みすると入力内容は消えます。社内文書や未公開のコードを比較する用途でも、ブラウザの外にデータが出ることはありません。
役立つTips
適切な比較モードの選び方
文章の校正なら「文字単位」、プログラムコードの修正確認なら「行単位」を選ぶのが基本です。句読点や助詞の細かな変更は文字単位で見ると差分箇所がひと目で分かります。
比較前に改行コードと空白をそろえる
このツールは改行コード・行末の空白・末尾改行の有無をすべて区別します。全行が赤と緑になったときは、内容ではなく CRLF/LF や空白の違いが原因である可能性が高いので、エディタ側で統一してから貼り直してください。
大きな変更は行単位で全体像をつかんでから
行単位で変更のある範囲を確認し、その範囲だけをコピーして文字単位で比較すると、計算も軽く、差分も読みやすくなります。文字単位で長文をそのまま比較すると、無関係な文字の一致が拾われて読みにくくなることがあります。
機密情報の取り扱い
このツールはブラウザ内で動作し、入力したテキストを外部に送信しません。社内文書や未公開コードの比較にも利用できますが、共有 PC ではブラウザを閉じる前に入力欄を空にしておくとより確実です。