PHP में दो तारों के बीच अंतर को हाइलाइट करें


136

PHP में दो तारों के बीच अंतर को उजागर करने का सबसे आसान तरीका क्या है?

मैं स्टैक ओवरफ्लो संपादित इतिहास पृष्ठ की तर्ज पर सोच रहा हूं, जहां नया पाठ हरे रंग में है और हटाए गए पाठ लाल रंग में है। यदि कोई पूर्व लिखित कार्य या कक्षाएं उपलब्ध हैं, तो यह आदर्श होगा।

जवाबों:


42

आप PHP Horde_Text_Diff पैकेज का उपयोग करने में सक्षम थे।

हालाँकि यह पैकेज अब उपलब्ध नहीं है।


1
लिंक अब काम नहीं करता है। यह 2011 में अब कोई अन्य समाधान है? ;-) क्या यह संभव है कि इस तरह के आउटपुट
मिलें

3
साइट निकल गई है, लेकिन आर्काइव.ऑर्ग के पास साइट की एक प्रति है: web.archive.org/web/20080506155528/http://software.zuavra.net/…
आर। हिल

15
बहुत बुरा यह PEAR की आवश्यकता है। PEAR- निर्भरता बेकार है।
रुडी

7
नई वेब साइट से: "अपडेट: इनलाइन रेंडरर अब Text_Diff PEAR पैकेज का मूल हिस्सा है। आपको अब यहां प्रस्तुत हैक का उपयोग करने की आवश्यकता नहीं है।" तो अभी Text_Diff का उपयोग करें।
Mat

11
GPL सिर्फ उपयोग करने के लिए स्वतंत्र नहीं है। यह आपके मॉड्यूल / प्रोजेक्ट को GPL होने के लिए भी बाध्य करता है।
पैरिस

76

बस एक स्ट्रिंग को दूसरे स्ट्रिंग में बदलने के लिए सबसे छोटी (शाब्दिक रूप से नहीं ली जाने वाली) संख्याओं की गणना करने के लिए एक वर्ग लिखा:

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

इसमें भिन्न रूप के HTML संस्करण को प्रस्तुत करने के लिए एक स्थिर कार्य है।

यह एक पहला संस्करण है, और इसमें सुधार की संभावना है, लेकिन यह अब तक ठीक काम करता है, इसलिए मैं इसे वहां फेंक रहा हूं जब किसी को एक कॉम्पैक्ट रूप से कुशलतापूर्वक उत्पन्न करने की आवश्यकता होती है, जैसे मुझे चाहिए।

संपादित करें: यह अब Github पर है: https://github.com/gorhill/PHP-FineDiff


3
मैं multibyte समर्थन पाने के लिए github.com/xrstf/PHP-FineDiff पर कांटा आज़माऊंगा !
activout.se

1
@R। हिल - मेरे लिए भी खूबसूरती से काम करता है। यह वास्तव में वर्तमान से बेहतर उत्तर है जो दोषपूर्ण प्रतीत होता है।
साने

कोई सुधार? यह कहता है कि फ़ाइल "टेक्स / डिफ.फैप" को शामिल करने में विफल रहा है और यह ज़िप में नहीं है।
14

गजब का! मेरा मतलब उदाहरण कोड के साथ ऑनलाइन डेमो है। एकदम चार-स्तर का अंतर। बस वाह! : ओ थैंक यू!
फ़िलिप ओवर्टोनसिंगर रिडो

2
ऐसा लगता है कि अब github.com/BillyNate/PHP-FineDiff कांटा सबसे आगे है और यह विभिन्न एन्कोडिंग वाले मल्टीबाइट्स का समर्थन करता है। github.com/xrstf/PHP-FineDiff @ activout.se 404ing है
Kangur

24

यदि आप एक मजबूत पुस्तकालय चाहते हैं, तो Text_Diff (एक PEAR पैकेज) बहुत अच्छा लग रहा है। इसमें कुछ बेहतरीन फीचर्स हैं।


6
PHP इनलाइन-डिफ, जैसा कि ऊपर उल्लेख किया गया है, "एक अंतर की गणना करने के लिए PEAR से Text_Diff"। :)
MN

लिंक टूट गया है। खिचड़ी पैकेज पाते हैं। यह वही Diff पैकेज है जिसका उपयोग Wordpress के नवीनतम संस्करण द्वारा किया जाता है।
तुलसी मूसा

24

यह एक अच्छा है, http://paulbutler.org/archives/a-simple-diff-al एल्गोरिदम-in-php/

समस्या को हल करना उतना आसान नहीं है जितना लगता है, और समस्या ने मुझे परेशान कर दिया, इससे पहले कि मैं इसका पता लगाऊं। मैं अपने एल्गोरिथ्म को PHP में, कोड की 18 लाइनों में लिखने में कामयाब रहा। यह एक अंतर करने के लिए सबसे कुशल तरीका नहीं है, लेकिन यह समझना सबसे आसान है।

यह दोनों तारों के लिए आम शब्दों के सबसे लंबे अनुक्रम को खोजने के द्वारा काम करता है, और जब तक सबस्ट्रिंग आम में कोई शब्द नहीं होता तब तक स्ट्रिंग के अवशेषों के सबसे लंबे अनुक्रमों का पता लगाता है। इस बिंदु पर यह एक प्रविष्टि के रूप में शेष नए शब्द और एक विलोपन के रूप में शेष पुराने शब्दों को जोड़ता है।

आप यहाँ स्रोत डाउनलोड कर सकते हैं: PHP सिंपलडिफ़ ...


1
मुझे यह बहुत उपयोगी लगा! नाशपाती सामान के रूप में जटिल नहीं है।
dgavey

यह मुझे एक गलतफहमी देता है:if($matrix[$oindex][$nindex] > $maxlen){ Undefined variable: maxlen
गतिशील

ठीक है कि आपने इसे हल करने के लिए एक कमेंट पोस्ट किया। :) आप इसे प्रारंभिक कोड में संपादित क्यों नहीं करते? धन्यवाद वैसे भी +1 ... हम्म अच्छी तरह से आप लेखक नहीं हैं
गतिशील

1
यहाँ 2010 से नवीनतम संस्करण प्रतीत होता है: github.com/paulgb/simplediff/blob/master/simpediff.php
rsk82

दरअसल, सादगी के लिए +1
पराग त्यागी

17

यहां एक छोटा फ़ंक्शन है जिसका उपयोग आप दो सरणियों को फैलाने के लिए कर सकते हैं। यह एलसीएस एल्गोरिथ्म को लागू करता है:

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

यह दो सरणियाँ उत्पन्न करता है:

  • मान सरणी: तत्वों की एक सूची के रूप में वे अंतर में दिखाई देते हैं।
  • मुखौटा सरणी: संख्याएँ होती हैं। 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> 

एसTackoerverफॉलओउटी

अतिरिक्त नोट्स:

  • भिन्न मैट्रिक्स के लिए (m + 1) * (n + 1) तत्वों की आवश्यकता होती है। यदि आप लंबे अनुक्रमों को अलग करने का प्रयास करते हैं तो आप मेमोरी त्रुटियों से बाहर निकल सकते हैं। इस मामले में पहले बड़े विखंडू (जैसे लाइनें) को अलग करें, फिर एक दूसरे पास में उनकी सामग्री को अलग करें।
  • एल्गोरिथ्म में सुधार किया जा सकता है यदि आप शुरू और अंत से मिलान तत्वों को ट्रिम करते हैं, तो एल्गोरिथ्म को केवल अलग-अलग मध्य पर चलाएं। एक बाद (अधिक फूला हुआ) संस्करण इन संशोधनों को भी शामिल हैं।

यह सरल, प्रभावी और क्रॉस-प्लेटफ़ॉर्म है; मैंने अलग-अलग आउटपुट प्राप्त करने के लिए विभिन्न सीमाओं (लाइन या शब्द) पर विस्फोट () के साथ इस तकनीक का उपयोग किया। बहुत अच्छा समाधान, धन्यवाद!
चाचा कोड बंदर

यह कहता हैcomputeDiff is not found
ichimaru

@ichimaru क्या आपने दोनों कार्य किए हैं?
कैलमेरियस

@ कलामरी ने दूसरा फंक्शन नहीं देखा ... कसम! इसके काम अब धन्यवाद!
इचिमारू

धन्यवाद, यह स्वीकार किए गए उत्तर की तुलना में भिन्न का पता लगाने में काफी आसान है।
करण शर्मा

6

XDiff के लिए एक PECL एक्सटेंशन भी है:

विशेष रूप से:

  • xdiff_string_diff - दो तारों का एकीकृत रूप बनाओ

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

1
xdiff pecl एक्सटेंशन अब बरकरार नहीं है, जाहिरा तौर पर एक स्थिर रिलीज 2008-07-01 के बाद से नहीं किया गया है, pecl.php.net/package/xdiff के अनुसार , मैंने स्वीकार किए गए उत्तर द्वारा सुझाव के साथ जाना समाप्त कर दिया क्योंकि यह बहुत नया है , horde.org/lbooks/Horde_Text_Diff/download
माइक

PHP के XDiff के लिए एक सरल संस्थापन प्रक्रिया है? (डेबियन लिनक्स के लिए)
पीटर क्रस

@MikePurcell, तथ्य की बात के रूप में, यह अभी भी कायम है। नवीनतम स्थिर संस्करण 2.0.1 समर्थन PHP 7 2016-05-16 को जारी किया गया है।
user2513149

@PeterKrauss, हाँ, वहाँ है। इस प्रश्न पर नज़र डालें: serverfault.com/questions/362680/…
user2513149

5

मुझे पीईआर-आधारित और दिखाए गए सरल विकल्पों दोनों के साथ भयानक परेशानी हुई। तो यहाँ एक समाधान है जो यूनिक्स डिफरेंस कमांड का लाभ उठाता है (जाहिर है, आपको यूनिक्स सिस्टम पर होना चाहिए या इसके लिए काम करने के लिए एक काम करने वाला विंडोज डिफेंड होना चाहिए)। अपनी पसंदीदा अस्थायी निर्देशिका चुनें, और यदि आप चाहें तो कोड वापस करने के लिए अपवाद बदलें।

/**
 * @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);
  }
}

4

यह सबसे अच्छा है जो मैंने पाया है।

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

यहां छवि विवरण दर्ज करें


3
UTF-8 के साथ ठीक से काम नहीं करता है। यह स्ट्रिंग्स पर ऐरे एक्सेस का उपयोग करता है, जो प्रत्येक चरित्र को एक बाइट वाइड के रूप में मानता है। Mb_split के साथ आसानी से ठीक करने योग्य होना चाहिए।
गेलवेइलर

1
यहाँ एक त्वरित सुधार है। बस के $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;
गेलवेइलर

यह क्लास फंक्शन कॉम्प्यूटटेबल में कैरेक्टर मोड का उपयोग करके मेमोरी से बाहर निकलता है।
एंडी

1
वर्तमान लिंक code.iamkate.com/php/diff-implementation है । मैंने इसका परीक्षण किया है और यह UTF-8 का समर्थन नहीं करता है।
Kangur

3

आप जो खोज रहे हैं वह एक "अलग एल्गोरिथ्म" है। एक त्वरित Google खोज ने मुझे इस समाधान के लिए प्रेरित किया । मैंने इसका परीक्षण नहीं किया, लेकिन शायद यह वही करेगा जो आपको चाहिए।


मैंने बस उस स्क्रिप्ट का परीक्षण किया है और यह अच्छी तरह से काम करता है - अंतर ऑपरेशन बहुत तेज़ी से पूरा होता है (मैंने जिस छोटे पैराग्राफ का परीक्षण किया, उसे संसाधित करने के लिए लगभग 10ms ले रहा हूं) और यह पता लगाने में सक्षम था कि लाइन ब्रेक कब जोड़ा गया था। जैसा कि कोड को चलाना है, PHP नोटिस के एक जोड़े को उत्पन्न करता है जिसे आप ठीक करना चाहते हैं, लेकिन इसके अलावा यह एक बहुत अच्छा समाधान है यदि आपको पारंपरिक साइड-बाय-साइड अंतर को देखने के बजाय अंतर को इनलाइन दिखाने की आवश्यकता है।
नोएल व्हिटमोर


2

मैं PHP कोर से इन भयानक कार्यों को देखने की सिफारिश करेंगे:

समान_टेक्स्ट - दो तारों के बीच समानता की गणना करें

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

लेवन्सहाइटिन - दो तारों के बीच लेवेन्सेटिन दूरी की गणना करें

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

साउंडएक्स - एक स्ट्रिंग के साउंडेक्स कुंजी की गणना करें

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

मेटाफोन - एक स्ट्रिंग की मेटाफोन कुंजी की गणना करें

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



हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.