2009-04-21 7 views
19

जब की तुलना समान लाइनों, मैं एक ही लाइन पर मतभेद हाइलाइट करना चाहते हैं:पायथन difflib: मतभेद इनलाइन हाइलाइटिंग?

a) lorem ipsum dolor sit amet 
b) lorem foo ipsum dolor amet 

lorem <ins>foo</ins> ipsum dolor <del>sit</del> amet 

difflib.HtmlDiff इनलाइन हाइलाइटिंग की इस तरह करने के लिए प्रतीत होता है, यह बहुत वर्बोज़ मार्कअप पैदा करता है।

दुर्भाग्य से, मैं एक और कक्षा/विधि नहीं ढूंढ पाया जो लाइन-दर-रेखा आधार पर संचालित नहीं होता है।

क्या मुझे कुछ याद आ रही है? किसी भी पॉइंटर्स की सराहना की जाएगी!

उत्तर

35

अपने सरल उदाहरण के लिए:

import difflib 
def show_diff(seqm): 
    """Unify operations between two compared strings 
seqm is a difflib.SequenceMatcher instance whose a & b are strings""" 
    output= [] 
    for opcode, a0, a1, b0, b1 in seqm.get_opcodes(): 
     if opcode == 'equal': 
      output.append(seqm.a[a0:a1]) 
     elif opcode == 'insert': 
      output.append("<ins>" + seqm.b[b0:b1] + "</ins>") 
     elif opcode == 'delete': 
      output.append("<del>" + seqm.a[a0:a1] + "</del>") 
     elif opcode == 'replace': 
      raise NotImplementedError, "what to do with 'replace' opcode?" 
     else: 
      raise RuntimeError, "unexpected opcode" 
    return ''.join(output) 

>>> sm= difflib.SequenceMatcher(None, "lorem ipsum dolor sit amet", "lorem foo ipsum dolor amet") 
>>> show_diff(sm) 
'lorem<ins> foo</ins> ipsum dolor <del>sit </del>amet' 

यह तार के साथ काम करता है। आपको यह तय करना चाहिए कि "प्रतिस्थापित" ऑपकोड के साथ क्या करना है।

+0

इसके लिए बहुत बहुत धन्यवाद! यह बिल्कुल आवश्यक नमूना है जिसकी मुझे आवश्यकता है। मुझे नहीं पता था कि कैसे शुरू किया जाए, लेकिन यह बहुत अच्छी तरह से दिखाता है। फिर से, बहुत धन्यवाद! – AnC

+0

+1 आपके उदाहरण के लिए धन्यवाद :) आप ऑप्टिकोड को प्रतिस्थापित करने के साथ क्या करने का सुझाव देंगे? – Viet

+0

ठीक है, जंगली में कुछ 'प्रतिस्थापन' ऑपकोड खोजने के लिए एक सुझाव होगा; प्रलेखन का कहना है कि उन्हें उत्पादित किया जा सकता है, लेकिन मुझे कभी भी किसी को भी याद नहीं है (आईआईआरसी मैंने केवल 'डिलीट के बाद' डालने के बाद देखा है)। किसी भी मामले में, 'प्रतिस्थापन' के साथ क्या करना है ओपी तक है। – tzot

2

difflib.SequenceMatcher एकल लाइनों पर काम करेगा। आप दूसरी लाइन बनाने के लिए पहली पंक्ति को बदलने के तरीके को निर्धारित करने के लिए "opcodes" का उपयोग कर सकते हैं।

+1

मुझे डर है कि मैं काफी यह समझ में नहीं आता हूँ - अभी तक वैसे भी, तो मैं अधिक खुदाई कर देंगे। धन्यवाद। – AnC

+0

आप मतभेदों के साथ क्या करने की कोशिश कर रहे हैं? क्या आप एचटीएमएल आउटपुट चाहते हैं या आप सिर्फ एचटीएमएलडिफ का उपयोग कर रहे थे क्योंकि यह लाइन में भिन्न था? – Adam

+0

जबकि एचटीएमएल आउटपुट मेरा प्राथमिक उपयोग मामला है, एचटीएमएलडिफ का आउटपुट आसान पुन: उपयोग करने की अनुमति नहीं देता है - यानी, अगर यह केवल आईएनएस और डीएल डालने वाला होता है, तो उसे आसानी से लाइन के नीचे जो कुछ भी चाहिए, उसे आसानी से बदल दिया जा सकता है। – AnC

0

यहाँ एक इनलाइन @ tzot के answer above (भी अजगर 3 संगत) से प्रेरित अलग है

def inline_diff(a, b): 
    import difflib 
    matcher = difflib.SequenceMatcher(None, a, b) 
    def process_tag(tag, i1, i2, j1, j2): 
     if tag == 'replace': 
      return '{' + matcher.a[i1:i2] + ' -> ' + matcher.b[j1:j2] + '}' 
     if tag == 'delete': 
      return '{- ' + matcher.a[i1:i2] + '}' 
     if tag == 'equal': 
      return matcher.a[i1:i2] 
     if tag == 'insert': 
      return '{+ ' + matcher.b[j1:j2] + '}' 
     assert false, "Unknown tag %r"%tag 
    return ''.join(process_tag(*t) for t in matcher.get_opcodes()) 

यह सही नहीं है - उदाहरण के लिए, यह विस्तार करने के लिए पूर्ण शब्द के बजाय प्रतिस्थापित पहचान करने के लिए opcodes 'की जगह ले' अच्छा होगा केवल कुछ अलग अक्षरों में से, लेकिन यह शुरू करने के लिए एक अच्छी जगह है।

नमूना उत्पादन:

>>> a='Lorem ipsum dolor sit amet consectetur adipiscing' 
>>> b='Lorem bananas ipsum cabbage sit amet adipiscing' 
>>> print(inline_diff(a, b)) 
Lorem{+ bananas} ipsum {dolor -> cabbage} sit amet{- consectetur} adipiscing 
संबंधित मुद्दे