突出显示两个string在PHP中的区别

在PHP中突出显示两个string之间的区别最简单的方法是什么?

我正在思考堆栈溢出编辑历史页面,新文本是绿色的,删除的文本是红色的。 如果有任何预先写好的function或类,那将是理想的。

您可以使用PHP Horde_Text_Diff包。 它适合你的需求,而且是相当可定制的。

它也是根据GPL许可的,所以享受!

刚刚写了一个类来计算最小的(不要从字面上)编辑的数量来将一个string转换为另一个string:

http://www.raymondhill.net/finediff/

它有一个静态函数来呈现diff版本的HTML版本。

这是第一个版本,可能会有所改进,但现在运行良好,所以我把它扔到那里,以防有人需要有效地生成紧凑的差异,就像我需要的那样。

编辑:现在在Github上: https : //github.com/gorhill/PHP-FineDiff

如果你想要一个健壮的库, Text_Diff (一个PEAR包)看起来相当不错。 它有一些非常酷的function。

这是一个很好的,也http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/

解决这个问题并不像看起来那么简单,这个问题让我困扰了大约一年,然后才明白了。 我设法用18行代码在PHP中编写我的algorithm。 这不是做差异的最有效的方法,但它可能是最容易理解的。

它的工作原理是find两个string共同的最长的单词序列,并recursion地findstring的剩余部分的最长序列,直到子string没有共同的单词为止。 此时,将剩余的新单词添加为插入,将剩余的旧单词添加为删除。

你可以在这里下载源代码: PHP SimpleDiff …

还有一个用于xdiff的PECL扩展:

尤其是:

  • xdiff_string_diff – 统一比较两个string

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; } 

这里有一个简短的函数可以用来区分两个数组。 它实现了LCSalgorithm:

 function computeDiff($from, $to) { $diffValues = array(); $diffMask = array(); $dm = array(); $n1 = count($from); $n2 = count($to); for ($j = -1; $j < $n2; $j++) $dm[-1][$j] = 0; for ($i = -1; $i < $n1; $i++) $dm[$i][-1] = 0; for ($i = 0; $i < $n1; $i++) { for ($j = 0; $j < $n2; $j++) { if ($from[$i] == $to[$j]) { $ad = $dm[$i - 1][$j - 1]; $dm[$i][$j] = $ad + 1; } else { $a1 = $dm[$i - 1][$j]; $a2 = $dm[$i][$j - 1]; $dm[$i][$j] = max($a1, $a2); } } } $i = $n1 - 1; $j = $n2 - 1; while (($i > -1) || ($j > -1)) { if ($j > -1) { if ($dm[$i][$j - 1] == $dm[$i][$j]) { $diffValues[] = $to[$j]; $diffMask[] = 1; $j--; continue; } } if ($i > -1) { if ($dm[$i - 1][$j] == $dm[$i][$j]) { $diffValues[] = $from[$i]; $diffMask[] = -1; $i--; continue; } } { $diffValues[] = $from[$i]; $diffMask[] = 0; $i--; $j--; } } $diffValues = array_reverse($diffValues); $diffMask = array_reverse($diffMask); return array('values' => $diffValues, 'mask' => $diffMask); } 

它生成两个数组:

  • values array:元素出现在diff中的列表。
  • 掩码数组:包含数字。 0:不变,-1:删除,1:增加。

如果使用字符填充数组,则可以使用它来计算内联差异。 现在只需要一个步骤来突出差异:

 function diffline($line1, $line2) { $diff = computeDiff(str_split($line1), str_split($line2)); $diffval = $diff['values']; $diffmask = $diff['mask']; $n = count($diffval); $pmc = 0; $result = ''; for ($i = 0; $i < $n; $i++) { $mc = $diffmask[$i]; if ($mc != $pmc) { switch ($pmc) { case -1: $result .= '</del>'; break; case 1: $result .= '</ins>'; break; } switch ($mc) { case -1: $result .= '<del>'; break; case 1: $result .= '<ins>'; break; } } $result .= $diffval[$i]; $pmc = $mc; } switch ($pmc) { case -1: $result .= '</del>'; break; case 1: $result .= '</ins>'; break; } return $result; } 

例如。:

 echo diffline('StackOverflow', 'ServerFault') 

会输出:

 S<del>tackO</del><ins>er</ins>ver<del>f</del><ins>Fau</ins>l<del>ow</del><ins>t</ins> 

小号 tackO erver F 福勒 stream Ť

补充笔记:

  • diffmatrix需要(m + 1)*(n + 1)个元素。 所以如果你试图比较长的序列,你可能会遇到内存不足的错误。 在这种情况下,首先比较大的块(例如线),然后在第二遍中分解它们的内容。
  • 如果您从头到尾对匹配元素进行修剪,则algorithm可以得到改进,然后仅在不同的中间运行algorithm。 后者(更臃肿)版本也包含这些修改。

这是我find的最好的一个。

http://code.stephenmorley.org/php/diff-implementation/

在这里输入图像描述

你在找什么是一个“差异algorithm”。 快速谷歌search引导我到这个解决scheme 。 我没有testing它,但也许它会做你所需要的。

我所遇到的以PEAR为基础的和简单的替代scheme都遇到了很大的麻烦。 所以这里有一个利用Unix diff命令的解决scheme(显然,你必须在Unix系统上或者有一个可用的Windows diff命令才能工作)。 select你最喜欢的临时目录,如果你愿意的话,改变例外返回代码。

 /** * @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的php端口diff_match_patch (Apache 2.0许可)

我会build议从PHP核心看这些令人敬畏的function:

similar_text – 计算两个string之间的相似度

http://www.php.net/manual/en/function.similar-text.php

levenshtein – 计算两串之间的Levenshtein距离

http://www.php.net/manual/en/function.levenshtein.php

soundex – 计算一个string的soundex键

http://www.php.net/manual/en/function.soundex.php

metaphone – 计算string的metaphone密钥

http://www.php.net/manual/en/function.metaphone.php

我遇到了基于Python difflib的Chris Boulton这个PHP差异类,这可能是一个很好的解决scheme:

PHP差异Lib

Interesting Posts