テキスト差分チェッカー

2つのテキストを比較して違いを瞬時に見つけます。

あなたのデータはデバイスを離れません

テキスト比較について

この差分ツールは、最長共通部分列(LCS)アルゴリズムを使って2つのテキストを行ごとに比較します。追加は緑で、削除は赤でハイライトされます。「インライン」ビューを選択すると、すべての変更が1つの列に表示され、「並べて」ビューでは元のテキストと変更されたテキストを並列に比較できます。

一般的な用途

よくある質問

文字ごとに比較しますか?

このツールは行ごとに比較します。行に少しでも変更がある場合(1文字でも)、行全体が変更済みとしてマークされます。これは、Gitとほとんどの差分ツールが使用するのと同じアプローチです。

サイズ制限はありますか?

厳密な制限はありませんが、非常に大きなテキスト(10,000行以上)は処理に時間がかかる場合があります。比較はブラウザ内で完全に実行されるためです。

「diff」とは実際何を意味するか

diffとは最小の挿入と削除のセットを使って1つのテキストを別のテキストに変換する方法を記述する。それを行う方法は無数にあり、最も単純なのは「Aの全文字を削除してからBの全文字を挿入する」だ。有用なdiffは最短編集スクリプトであり、これは最長共通部分列問題の双対だ:両テキストに(順序どおりに)現れる最長の行の列を見つけ、それ以外の全ては追加または削除だ。ほとんどのdiffアルゴリズムは異なる装いをしたLCSアルゴリズムだ。

微妙な点がある:最長共通部分列は最長共通部分文字列ではない。部分列は順序を保持するが隣接は不要だ。そのため「ABCDE」と「AXBYCZD」は3文字の連続した文字列が両方に現れないにもかかわらず、部分列「ABCD」を共有する。

diffアルゴリズムの略史

最初に広く使われたファイル比較プログラムはBell LabsのUnix用diffで、Douglas McIlroyが作成し、基礎アルゴリズムは1976年6月のBell Labs Computing Science Technical Report #41としてJames W. HuntとMcIlroyが発表した。McIlroy自身は4ヶ月の開発を「必死の努力」と表現した。Hunt-McIlroyのアプローチはファイルBの各行をハッシュ化してユニークな行の出現箇所をインデックス化し、最長の単調増加マッチチェーンを探した。Version 6 Unixに収録され、何十年もの間ほとんどのUnixシステムの/usr/bin/diffで本質的に同じアルゴリズムのまま使われ続けた。

Eugene W. Myersは1986年に現代の業界標準を発表した。Algorithmica Vol.1, No.2に掲載された「O(ND)差分アルゴリズムとその変形」だ。Myersは編集グラフを通じた最短経路問題としてLCSを再定義した:Aを上軸、Bを側軸に配置し、2行が一致するたびに対角線を引き、非対角辺の最も少ない左上から右下へのパスを探す。各非対角辺は1回の挿入または削除で、各対角線はコストゼロだ。重要なのは、アルゴリズムがDを編集スクリプトのサイズとしてO((N+M)·D)時間で動作すること、つまりファイルが類似しているほど高速化されることだ。一般的なバージョン管理のdiffではDはN+Mに比べてごく小さいため、Myersは実際にはO(N·M)の最悪ケースより劇的に高速だ。論文にはまた、分割統治の「ミドルスネーク」技法を使った線形空間改良版も含まれる。Myersのアルゴリズムは、GNU diff・git diff・Mercurial・Subversion・jsdiff・Pythonのdifflib・ほとんどのGUI diffビューアーのデフォルトバックエンドだ。

Bram Cohen(後にBitTorrentの発明者として知られるようになる)は2002年頃にBazaarバージョン管理システム向けにパティエンスdiffを設計した。動機となった問題:Myersのdiffは非常に一般的な行も含めて任意の一致行を整列させるため、Cでの関数移動が、移動した関数の閉じ括弧が無関係な関数の閉じ括弧と整列するノイズの多いdiffを生む可能性があった。パティエンスdiffは各ファイルに1回だけ現れる行(通常は関数シグネチャ・コメントヘッダー・特徴的なログメッセージ)でdiffを固定し、パティエンスソートを使ってそれらのアンカーだけのLCSを計算し、ギャップで再帰する。結果として意味のある行で整列し、ソースコードに対してより読みやすくなる。Gitではgit diff --patienceで使用できる。ヒストグラムdiffは2010年頃にgitに追加された改良版で、行の出現回数のヒストグラムを構築し、厳密なユニーク行ではなく低頻度のアンカーを優先する。git 2.45以降、多くの設定でデフォルトとなっている。

レーベンシュタインとLCS

区別する価値のある関連概念だ。レーベンシュタイン距離(Vladimir Levenshtein、1965年)は1つの文字列を別の文字列に変換するための1文字の挿入・削除・置換の最小回数を数える。LCSベースのdiffは密接に関連するが若干異なる:古典的なdiffは「変更」を単一の置換ではなく削除と挿入のペアとして扱う。これが行指向ファイルにより適しているためだ。レーベンシュタインは「これらの文字列はどれだけ異なるか?」に答えて数値を返す。LCSは「具体的に何が変わったか?」に答えて実際の編集スクリプトを返す。スペルチェッカーや「もしかして?」機能は前者を求め、diffツールは後者を求める。Damerau-Levenshteinバリアント(1964年)は誤字検出のためのトランスポジション演算子でレーベンシュタインを拡張する。

粒度:行・単語・文字

diffは異なる粒度で計算でき、それぞれにトレードオフがある:

現代のdiff UIで一般的なパターンは、まず行レベルでdiffを計算し、「削除/追加の隣接ペア」のそれぞれに対してその2行だけに二次的な単語レベルdiffを実行し、行内の変更をハイライトすることだ。これはGitHubのPRビューとdiff-match-patchライブラリの両方の動作方法だ。

よく見かける3つのdiff表示モード

便利なgit diffのバリアント

ブラウザdiffを使う場面

正直な制限事項

さらなる質問

なぜこのページは変更された行内の文字レベルのハイライトを表示しないのですか?

行レベルの処理はほとんどのユースケースに十分で、長い入力でも大幅に高速なためだ。行内の単語ごとのハイライトには2段階の精製が標準的だが、レイテンシーが増加する。行全体の差異が重要な場合(法的レッドライン・散文の校正)は、専用の単語レベルツール(コマンドラインのgit diff --word-diffなど)の方が適している。

ユニファイドdiffとサイドバイサイドの違いは何ですか?

ユニファイドdiffは全ての.patchファイルが使うコンパクトで機械可読な形式で、3行のコンテキストとhunksを@@でマークする。サイドバイサイドは2つのバージョンを並列列で表示し、視覚的なレビューには目に優しいが横方向のスペースを多く取る。ユニファイドはメールやコミットに使い、サイドバイサイドは広いモニターで読む。

ソースコードにはMyersより優れたアルゴリズムがありますか?

関数の移動や大規模な再配置があるソースコードには、はい、パティエンスdiff(Bram Cohen、2002年)とヒストグラムdiff(git、2010年頃)は一般的な行ではなく意味のあるユニーク行で整列するように設計されており、より読みやすい出力を生成する。どちらもgit diff --patiencegit diff --histogramで利用できる。difftasticのようなAST対応ツールはさらに進んで実際の言語構造を解析する。

機密テキストをここに貼り付けても安全ですか?

はい、diffはJavaScriptのLCS実装を使いブラウザ内で完全に動作する。何もアップロードされず、入力に関するアナリティクスもなく、テキストのサーバー側ログもない。これはNDA・内部ソースコード・未公開の契約条項に安全なdiffツールの唯一のカテゴリーだ。クラウドベースのdiffサービスは貼り付けた内容を閲覧できる。

関連ツール