PHP で 2 つの文字列の違いを強調する最も簡単な方法は何ですか?
Stack Overflow の編集履歴ページの行に沿って考えています。新しいテキストは緑で、削除されたテキストは赤です。事前に作成された関数またはクラスが利用可能であれば、それが理想的です。
ある文字列を別の文字列に変換するための編集の最小数 (文字通りに解釈されない) を計算するクラスを作成しました。
http://www.raymondhill.net/finediff/
差分の HTML バージョンをレンダリングする静的関数があります。
これは最初のバージョンであり、改善される可能性がありますが、今のところ問題なく動作するため、必要に応じて誰かがコンパクトな差分を効率的に生成する必要がある場合に備えて、そこに捨てています。
編集: 現在 Github にあります: https://github.com/gorhill/PHP-FineDiff
PHP Horde_Text_Diff パッケージを使用できました。
ただし、このパッケージは使用できなくなりました。
これは素晴らしいものです 。http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/
問題の解決は見た目ほど簡単ではなく、問題が解決するまでに約1年間悩みました。アルゴリズムをPHPで18行のコードで書くことができました。差分をとるのに最も効率的な方法ではありませんが、おそらく理解するのが最も簡単です。
これは、両方の文字列に共通する単語の最長シーケンスを検索し、サブ文字列に共通の単語がなくなるまで、文字列の残りの部分の最長シーケンスを再帰的に検索することによって機能します。この時点で、残りの新しい単語を挿入として追加し、残りの古い単語を削除として追加します。
ここからソースをダウンロードできます:PHPSimpleDiff ..。
堅牢なライブラリが必要な場合は、Text_Diff (PEAR パッケージ) がかなり良さそうです。それはいくつかのかなりクールな機能を備えています。
xdiff の PECL 拡張もあります。
特に:
PHP マニュアルの例:
<?php
$old_article = file_get_contents('./old_article.txt');
$new_article = $_POST['article'];
$diff = xdiff_string_diff($old_article, $new_article, 1);
if (is_string($diff)) {
echo "Differences between two articles:\n";
echo $diff;
}
示されているPEARベースの代替案とより単純な代替案の両方でひどい問題が発生しました。したがって、Unixのdiffコマンドを利用するソリューションを次に示します(明らかに、Unixシステムを使用しているか、Windowsのdiffコマンドが機能している必要があります)。お気に入りの一時ディレクトリを選択し、必要に応じて例外を変更してコードを返します。
/**
* @brief Find the difference between two strings, lines assumed to be separated by "\n|
* @param $new string The new string
* @param $old string The old string
* @return string Human-readable output as produced by the Unix diff command,
* or "No changes" if the strings are the same.
* @throws Exception
*/
public static function diff($new, $old) {
$tempdir = '/var/somewhere/tmp'; // Your favourite temporary directory
$oldfile = tempnam($tempdir,'OLD');
$newfile = tempnam($tempdir,'NEW');
if (!@file_put_contents($oldfile,$old)) {
throw new Exception('diff failed to write temporary file: ' .
print_r(error_get_last(),true));
}
if (!@file_put_contents($newfile,$new)) {
throw new Exception('diff failed to write temporary file: ' .
print_r(error_get_last(),true));
}
$answer = array();
$cmd = "diff $newfile $oldfile";
exec($cmd, $answer, $retcode);
unlink($newfile);
unlink($oldfile);
if ($retcode != 1) {
throw new Exception('diff failed with return code ' . $retcode);
}
if (empty($answer)) {
return 'No changes';
} else {
return implode("\n", $answer);
}
}
あなたが探しているのは「差分アルゴリズム」です。簡単なグーグル検索で、この解決策にたどり着きました。私はそれをテストしませんでしたが、おそらくあなたが必要とすることをするでしょう.
Neil Frasers diff_match_patch の php ポート(Apache 2.0 ライセンス)
PHPコアのこれらの素晴らしい関数を見ることをお勧めします:
similar_text — 2 つの文字列間の類似度を計算する
http://www.php.net/manual/en/function.similar-text.php
levenshtein — 2 つの文字列間のレーベンシュタイン距離を計算する
http://www.php.net/manual/en/function.levenshtein.php
soundex — 文字列の soundex キーを計算する
http://www.php.net/manual/en/function.soundex.php
metaphone — 文字列の metaphone キーを計算する
Python difflib に基づいた Chris Boulton によるこの PHP diff クラスに出会いました。これは良い解決策になる可能性があります。