2012-05-07 18 views
8

Tengo dos archivos A y B. Quiero encontrar todas las líneas en A que no están en B. ¿Cuál es la forma más rápida de hacer esto en bash/utilizando las utilidades estándar de Linux? Esto es lo que intenté hasta ahora:¿Cómo encontrar la diferencia establecida de dos archivos?

for line in `cat file1` 
do 
    if [ `grep -c "^$line$" file2` -eq 0]; then 
    echo $line 
    fi 
done 

Funciona, pero es lento. ¿Hay una manera más rápida de hacer esto?

+0

¿Puede mostrar algún código o explicar lo que ha intentado? Tu pregunta, tal como está, hace que parezca que quieres que hagamos todo el trabajo por ti. A menudo, mostrar el código ayudará a fomentar más respuestas y mejores resultados. – jmort253

+0

También debe definir lo que espera por "más rápido". Se trata del tiempo de procesamiento o el tiempo dedicado a escribir el código. Por el segundo, iría por algo como 'diff A B | grep '^ -' ' – tonio

+0

@ jmort253, gracias, he editado la pregunta para agregar más detalles – spinlok

Respuesta

20

The BashFAQdescribes doing exactly this with comm, que es el método canónicamente correcta.

# Subtraction of file1 from file2 
# (i.e., only the lines unique to file2) 
comm -13 <(sort file1) <(sort file2) 

diff es menos apropiado para esta tarea, ya que trata de operar en bloques en lugar de líneas individuales; como tal, los algoritmos que tiene que usar son más complejos y menos eficientes en la memoria.

comm ha sido part of the Single Unix Specification desde SUS2 (1997).

+0

¡Esto es exactamente lo que estaba buscando! ¡Gracias! – spinlok

+0

Eso es un programa útil. No he visto eso antes. Me pregunto qué otras pequeñas gemas de aplicaciones de shell perdieron mi vida pasada como administrador de sistemas. –

1

El programa 'diff' es el programa estándar de Unix que analiza las diferencias entre los archivos.

% cat A 
a 
b 
c 
d 
% cat B 
a 
b 
e 
% diff A B 
3,4c3 
< c 
< d 
--- 
> e 

Con un simple grep y cortar uno puede seleccionar las líneas A, no en B. Tenga en cuenta que el corte es bastante simplista y espacios en las líneas sería tirarlo fuera ... pero el concepto es allí.

% diff A B | grep '^<' | cut -f2 -d" " 
c 
d 
2

Si simplemente desea que las líneas que se encuentran en el archivo A, pero no en B, puede ordenar los archivos, y compararlos con diff.

sort A > A.sorted 
sort B > B.sorted 
diff -u A.sorted B.sorted | grep '^-' 
+4

No necesita archivos temporales para eso. 'diff <(sort A) <(sort B) | grep '^ -' ' – jordanm

+0

Sí, está aún más claro de esta manera, gracias – tonio

Cuestiones relacionadas