답변:
PHP Horde_Text_Diff 패키지를 사용할 수있었습니다.
그러나이 패키지는 더 이상 사용할 수 없습니다.
하나의 문자열을 다른 문자열로 변환하기 위해 가장 적은 수의 편집을 계산하기 위해 클래스를 작성했습니다.
http://www.raymondhill.net/finediff/
diff의 HTML 버전을 렌더링하는 정적 함수가 있습니다.
그것은 첫 번째 버전이며 개선 될 가능성이 있지만 지금은 잘 작동하므로 누군가가 필요로하는 것처럼 컴팩트 한 diff를 효율적으로 생성 해야하는 경우에 대비하여 버리고 있습니다.
편집 : 그것은 지금 Github에 있습니다 : https://github.com/gorhill/PHP-FineDiff
강력한 라이브러리를 원한다면 Text_Diff (PEAR 패키지)가 꽤 좋아 보입니다. 꽤 멋진 기능이 있습니다.
이것은 또한 좋은 것입니다, http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/
문제를 해결하는 것은 생각만큼 간단하지 않으며 문제를 파악하기 전에 약 1 년 동안 문제가 발생했습니다. 18 줄의 코드로 PHP로 알고리즘을 작성할 수있었습니다. diff를 수행하는 가장 효율적인 방법은 아니지만 아마도 이해하기가 가장 쉽습니다.
두 문자열에 공통적 인 가장 긴 단어 시퀀스를 찾고 하위 문자열에 공통된 단어가 없을 때까지 나머지 문자열의 가장 긴 시퀀스를 재귀 적으로 찾습니다. 이 시점에서 나머지 새 단어를 삽입으로, 나머지 오래된 단어를 삭제로 추가합니다.
여기에서 소스를 다운로드 할 수 있습니다 : PHP SimpleDiff ...
if($matrix[$oindex][$nindex] > $maxlen){
Undefined variable: maxlen
다음은 두 배열을 비교하는 데 사용할 수있는 간단한 기능입니다. LCS 알고리즘을 구현합니다 .
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);
}
두 개의 배열을 생성합니다.
배열을 문자로 채우면 인라인 차이를 계산하는 데 사용할 수 있습니다. 이제 차이점을 강조하기위한 단 한 단계 만 수행하십시오.
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>
에스압정에버에프폴아야티
추가 사항 :
computeDiff is not found
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);
}
}
이것은 내가 찾은 최고의 것입니다.
$sequence1 = $string1; $sequence2 = $string2; $end1 = strlen($string1) - 1; $end2 = strlen($string2) - 1;
와 함께$sequence1 = preg_split('//u', $string1, -1, PREG_SPLIT_NO_EMPTY); $sequence2 = preg_split('//u', $string2, -1, PREG_SPLIT_NO_EMPTY); $end1 = count($sequence1) - 1; $end2 = count($sequence2) - 1;
당신이 찾고있는 것은 "diff algorithm"입니다. 빠른 Google 검색 으로이 솔루션으로 연결되었습니다 . 나는 그것을 테스트하지 않았지만 어쩌면 그것은 당신이 필요한 것을 할 것입니다.
Neil Frasers의 PHP 포트 diff_match_patch (Apache 2.0 라이센스)
PHP 코어 에서이 멋진 기능을 보는 것이 좋습니다.
similar_text — 두 문자열 사이의 유사성을 계산
http://www.php.net/manual/en/function.similar-text.php
levenshtein — 두 줄 사이의 Levenshtein 거리를 계산
http://www.php.net/manual/en/function.levenshtein.php
soundex — 문자열의 soundex 키를 계산
http://www.php.net/manual/en/function.soundex.php
metaphone — 문자열의 메타 폰 키를 계산합니다
좋은 해결책이 될 수있는 Python difflib을 기반으로 Chris Boulton이 작성한 PHP diff 클래스를 발견했습니다.
https://github.com/danmysak/side-by-side : 다른 솔루션 (통일보기와 비교하여 나란히 비교하기위한) .