Salida de las líneas comunes (similitudes) de dos archivos de texto (lo contrario de diff)?

21

Diff es una gran herramienta para mostrar los cambios entre dos archivos. Pero, ¿cómo mostrar las similitudes de dos archivos de texto (sin tener en cuenta las diferencias)?

Es decir, entrada de muestra:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo salida (algo como esto):

@@ 2,3
=Hello World

Simplemente ordenar ambos archivos y usar comm no es suficiente, porque en ese caso se pierde la información de la línea.

maxschlepzig
fuente

Respuestas:

24

¿Qué tal usar diff, aunque no quieras un diff? Prueba esto:

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

Esto es lo que obtengo con sus datos de muestra:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World
Mike Gray
fuente
2
Puede evitar incrustar una nueva línea literal como esta:...%df'$'\n''%<'...
pausa hasta nuevo aviso.
1
También puede hacerlo así: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Tenga en cuenta las comillas dobles.)
pausa hasta nuevo aviso.
¡Buena cosa! No conocía estas opciones, porque solo miré la página de manual de diff ...
maxschlepzig
Estoy usando diff --version diff (GNU diffutils) 2.8.1 Y obtengo el siguiente error: diff: opciones de estilo de salida en conflicto diff: Intente 'diff --help' para obtener más información.
Sujay
Estaba recibiendo "error: diff: opciones de estilo de salida en conflicto diff" porque tenía un alias de diferencias definido. Use which diffpara ver si este es su problema.
justinjhendrick
14
grep -Fxf file1 file2

-Fsignifica emparejar cadenas simples (no expresiones regulares), -xsignifica solo coincidencias de línea completa, -fsignifica tomar 'patrones' (es decir, líneas) del archivo nombrado como argumento

tobyodavies
fuente
3
¿No están -fe -Fintercambiados ?. Al menos en mi grepversión es así. Necesito proporcionar file2información al -fargumento, como cat file1 | grep -Fxf file2, y luego funciona.
Birei
Esto no me funcionó.
Chaminda Bandara
7

commpuede ser usado. man commpara todas las opciones, pero querrá usar comm -12 ...para mostrar solo las líneas que existen en ambas entradas.

Como la gente ha señalado, sortprimero debe pasar su opinión .

Oli
fuente
1
Hm, eso funciona solo para líneas comunes que están en el mismo número de línea en ambos archivos.
maxschlepzig
2
comm parece ser solo para archivos ordenados y no para dar esa salida útil para el caso de uso del OP. Su ejemplo: $ comm -12 ab Hello World comm: el archivo 1 no está ordenado comm: el archivo 2 no está ordenado
Marcel Stimberg
@maxschlepzig: debe ordenar sus archivos antes de pasarlos a com.
Hemant
2
Sin embargo, al ordenar se deshace de toda la información sobre la posición de las líneas comunes. Tampoco ordenaría los archivos antes de compararlos con diff.
Marcel Stimberg
7

No creo que haya un solo comando que haga lo que quieres que haga. Sin embargo, puede intentar combinar la salida de diffcon grep. Si sus archivos de texto contienen ninguno de los personajes |, <, >, el siguiente le da salida de cierta utilidad:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World
Marcel Stimberg
fuente
Pruebe esto:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
pausa hasta nuevo aviso.
eso se ve mejor, pero debe incluir <y> en el grep para deshacerse también de las líneas agregadas en cualquier archivo.
Marcel Stimberg
2

Dick Grune escribió una familia de herramientas para este tipo de cosas:

http://dickgrune.com/Programs/similarity_tester/

Hay versiones que analizan la sintaxis de varios idiomas, de modo que cosas como las variables renombradas pueden verse sin cambios.

Está empaquetado como similarity-testeren Debian y Ubuntu.

Douglas Bagnall
fuente