2012-06-22 35 views
19

Ok, tengo dos listas relacionadas en mi máquina Linux en archivos de texto:Bash - Diferencia entre dos listas

/tmp/oldList 
/tmp/newList 

tengo que comparar estas listas para ver lo consiguieron añaden líneas y lo consiguieron líneas eliminan. Necesito hacer un ciclo sobre estas líneas y realizar acciones en ellas en función de si se agregaron o eliminaron. ¿Cómo hago esto en bash?

+0

La misma pregunta fue hecha 4 días antes http://stackoverflow.com/questions/11099894/comparing-2-unsorted-lists-in-linux-listing-the-unique-in-the-second-file/11101143 # 11101143 –

Respuesta

50

Utilice el comando comm(1) para comparar los dos archivos. Ambos deben estar ordenados, lo que puedes hacer de antemano si son grandes, o puedes hacerlo en línea con bash sustitución de proceso.

comm puede tomar una combinación de las banderas -1, -2 y -3 que indican qué archivo para suprimir líneas de (únicos para presentar 1, únicos para presentar 2 o comunes a ambos).

Para obtener las líneas sólo en el archivo antiguo:

comm -23 <(sort /tmp/oldList) <(sort /tmp/newList) 

Para obtener las líneas sólo en el nuevo archivo:

comm -13 <(sort /tmp/oldList) <(sort /tmp/newList) 

se puede alimentar a que en un bucle while read para procesar cada línea :

while read old ; do 
    ...do stuff with $old 
done < <(comm -23 <(sort /tmp/oldList) <(sort /tmp/newList)) 

y análogamente para las nuevas líneas.

4

El diff command hará la comparación por usted.

por ejemplo,

$ diff /tmp/oldList /tmp/newList 

Véase el vínculo hombre arriba para obtener más información. Esto debería encargarse de su primera parte de su problema.

+1

Simplemente enfatizaré que el comando 'diff' tiene un número ridículo de opciones para formatear el resultado, lo que podría proporcionar una entrada conveniente para el programa que procesará las diferencias. – chepner

+0

@chepner buen punto ... definitivamente vale la pena revisar la página del hombre vinculado. – Levon

0

Ha intentado diff

$ diff /tmp/oldList /tmp/newList 

$ man diff 
2

Considere usar Ruby si sus scripts necesitan legibilidad.

Para obtener las líneas sólo en el archivo antiguo:

ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')" 

Para obtener las líneas sólo en el nuevo archivo:

ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')" 

se puede alimentar a eso en un tiempo leer bucle para procesar cada línea:

while read old ; do 
    ...do stuff with $old 
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')" 
1

Esto es antiguo, pero para completarlo, deberíamos decir que si tiene un conjunto realmente grande, los ayunos t solución sería utilizar diff para generar una secuencia de comandos y luego la fuente él, como este: aparecerán

#!/bin/bash 

line_added() { 
    # code to be run for all lines added 
    # $* is the line 
} 

line_removed() { 
    # code to be run for all lines removed 
    # $* is the line 
} 

line_same() { 
    # code to be run for all lines at are the same 
    # $* is the line 
} 

cat /tmp/oldList | sort >/tmp/oldList.sorted 
cat /tmp/newList | sort >/tmp/newList.sorted 

diff >/tmp/diff_script.sh \ 
    --new-line-format="line_added %L" \ 
    --old-line-format="line_removed %L" \ 
    --unchanged-line-format="line_same %L" \ 
    /tmp/oldList.sorted /tmp/newList.sorted 

source /tmp/diff_script.sh 

líneas cambiadas como eliminado y añadido. Si no te gusta esto, puedes usar --changed-group-format. Verifique la página de manual de diff.

Cuestiones relacionadas