python diff

diff python sympy



Python difflib: destacando las diferencias en lĂ­nea? (3)

Aquí hay una diferencia en línea inspirada en la respuesta de @tzot anterior (también compatible con Python 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())

No es perfecto; por ejemplo, sería bueno expandir los códigos de operación "reemplazar" para reconocer la palabra completa reemplazada en lugar de solo las pocas letras diferentes, pero es un buen lugar para comenzar.

Salida de muestra:

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

Al comparar líneas similares, quiero resaltar las diferencias en la misma línea:

a) lorem ipsum dolor sit amet b) lorem foo ipsum dolor amet lorem <ins>foo</ins> ipsum dolor <del>sit</del> amet

Si bien difflib.HtmlDiff parece hacer este tipo de resaltado en línea, produce un marcado muy detallado.

Desafortunadamente, no he podido encontrar otra clase / método que no funcione línea por línea.

¿Me estoy perdiendo algo? ¡Cualquier indicador sería apreciada!


Para su ejemplo simple:

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''

Esto funciona con cuerdas. Debe decidir qué hacer con los códigos de operación "reemplazar".


difflib.SequenceMatcher operará en líneas simples. Puede usar los "códigos de operación" para determinar cómo cambiar la primera línea para convertirla en la segunda línea.