2009-04-14 27 views
137

Tengo una serie de archivos de texto para los cuales me gustaría saber las líneas en común en lugar de las líneas que son diferentes entre ellos. La línea de comandos Unix o Windows está bien.cómo mostrar líneas en común (diff inverso)?

foo:

linux-vdso.so.1 => (0x00007fffccffe000) 
libvlc.so.2 => /usr/lib/libvlc.so.2 (0x00007f0dc4b0b000) 
libvlccore.so.0 => /usr/lib/libvlccore.so.0 (0x00007f0dc483f000) 
libc.so.6 => /lib/libc.so.6 (0x00007f0dc44cd000) 

barra:

libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f716ae22000) 
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f716a96d000) 
linux-vdso.so.1 => (0x00007fffccffe000) 

Por lo tanto, teniendo en cuenta estos dos archivos por encima de la salida de la utilidad deseada sería similar a file1:line_number, file2:line_number == matching text (sólo una sugerencia, realmente no lo hacen importa cuál es la sintaxis):

foo:1, bar:3 == linux-vdso.so.1 => (0x00007fffccffe000) 

gracias.

+0

@ChristopherSchultz Mi error. 1.ª línea en el primer ejemplo supuesta coincidencia última línea en el 2.º ejemplo. Gracias por captar el error; cambiando. –

+1

Otra pregunta similar con buenas respuestas: http://unix.stackexchange.com/questions/1079/output-the-common-lines-similarities-of-two-text-files-the-opposite-of-diff – MortezaE

Respuesta

169

En * nix, puede usar comm. La respuesta a la pregunta es:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted 

Aquí está el uso completo de comm:

comm [-1] [-2] [-3 ] file1 file2 
-1 Suppress the output column of lines unique to file1. 
-2 Suppress the output column of lines unique to file2. 
-3 Suppress the output column of lines duplicated in file1 and file2. 

También tenga en cuenta que es importante para ordenar los archivos antes de utilizar comunicaciones, como se menciona en las páginas man.

+1

comm [ -1] [-2] [-3] archivo1 archivo2 -1 Suprime la columna de salida de las líneas exclusivas del archivo1. -2 Suprime la columna de salida de líneas exclusivas de file2. -3 Suprime la columna de salida de líneas duplicadas en file1 y file2. – ojblass

+0

@ojblass: Agregué esto a la respuesta. –

+3

Descubrí que es importante que los archivos sean ordenados antes de usar comm. Quizás agregue eso a la respuesta. –

32

se le preguntó aquí antes: Unix command to find lines common in two files

También puede probar con el Perl (crédito goes here)

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2 
+1

gracias. Me hubiera gustado aceptar ambas respuestas, ya que el delineador de Perl es multiplataforma. Comm recibe el visto bueno porque es más simple. –

+0

nada de malo con una solución alternativa :) – Chris

+0

Perfecto. El uso de la terminal cygwin en Windows y 'comm' no estaba disponible. Esta fue la alternativa perfecta. – Qix

11

simplemente he aprendido el comando de comunicaciones de este hilo, pero quería añadir algo extra: si el los archivos no están ordenados, y no desea tocar los archivos originales, puede canalizar la salida del comando ordenar. Esto deja intactos los archivos originales. Funciona en bash, no puedo decir sobre otras conchas.

comm -1 -2 <(sort file1) <(sort file2) 

Esto se puede ampliar para comparar la salida del comando, en lugar de archivos:

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort) 
35

consideran que esta respuesta en a question listed as a duplicate. Encuentro grep para ser más-admin ambiente que comm, así que si lo que desea es el conjunto de las líneas que coincidan (útil para comparar CSV, por ejemplo) simplemente utilizar la versión

grep -F -x -f file1 file2 

o la fgrep simplificado

fgrep -xf file1 file2 

Además, puede usar file2* para agrupar y buscar líneas en común con varios archivos, en lugar de solo dos.

Algunas otras variaciones adicionales se incluyen:

  • -n bandera para mostrar el número de línea de cada línea encajada
  • -c sólo a contar el número de líneas que concuerdan con
  • -v para mostrar sólo las líneas en archivo2 que difieren (o usa diff).

El uso de comm es más rápido, pero esa velocidad se produce a expensas de tener que ordenar los archivos primero. No es muy útil como una "diferencia inversa".

+0

gracias Ryder, esto podría ser más útil que comunica a muchos. Debes enlazar con la respuesta de origen (hay más de media docena enlazadas en Q en el navegador de la derecha, es un poco difícil de encontrar). También sería bueno saber qué tan bien funciona grep con una entrada ordenada de manera diferente o diferente, y puede imprimir los números de línea correspondientes de las coincidencias. –

+0

@mattwilkie - hecho! – Ryder

+1

@mattwilkie Sentí la necesidad de volver y aclarar el uso de la bandera '-v' después de que me equivoqué. Digamos que tiene dos archivos csv file1 y file2, y tienen filas superpuestas y no superpuestas. Si desea todas y solo las filas no superpuestas, usar 'fgrep -v archivo1 archivo2' solo devolverá las filas que no se superponen en el archivo2, * y ninguna de las filas adicionales que no se superponen en el archivo1 *. Esto puede ser obvio para algunos, pero es mejor decir lo obvio que la mala interpretación del riesgo. En este caso particular, clasificar los archivos y usar 'comm' sigue siendo la mejor opción. – Ryder

1

Sólo para obtener información, hice una pequeña herramienta para Windows haciendo lo mismo que "grep -F -f -x archivo1 archivo2" (ya que no he encontrado nada equivalente a este comando en Windows)

aquí está: http://www.nerdzcore.com/?page=commonlines

uso es "CommonLines inputFile1 inputFile2 outputFile"

El código fuente está también disponible (GPL)

5

manera más fácil de hacer es:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2 

No es necesario clasificar los archivos.

+0

Esto no se parece a la mayoría de las respuestas aquí, ya que le permite reconstruir las plantillas de origen. Tengo dos archivos creados desde el mismo contenedor, con texto diferente insertado en algunos puntos. Esta respuesta me permitió recuperar el contenedor. –

Cuestiones relacionadas