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.