2012-06-22 18 views
19

Ok, ho due liste correlate sulla mia macchina Linux in file di testo:Bash - Differenza tra due liste

/tmp/oldList 
/tmp/newList 

ho bisogno di confrontare queste liste per vedere che cosa ha ottenuto aggiunti linee e quali linee ottenuto rimossi. Ho quindi bisogno di eseguire il loop su queste linee ed eseguire azioni su di esse in base al fatto che siano state aggiunte o rimosse. Come faccio a farlo in bash?

+0

La stessa domanda è stata posta 4 giorni prima http://stackoverflow.com/questions/11099894/comparing-2-unsorted-lists-in-linux-listing-the-unique-in-the-second-file/11101143 # 11101143 –

risposta

50

Utilizzare il comando comm(1) per confrontare i due file. Entrambi devono essere ordinati, cosa che puoi fare in anticipo se sono grandi, oppure puoi farlo in linea con la sostituzione del processo .

comm può prendere una combinazione delle bandiere -1, -2 e -3 indicano quale file sopprimere linee da (unici per depositare 1, unici per presentare 2 o comuni ad entrambi).

Per ottenere le linee solo nel vecchio file:

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

Per ottenere le linee solo nel nuovo file:

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

è possibile alimentare che in un ciclo while read per elaborare ogni riga :

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

e analogamente per le nuove linee.

4

Il diff command eseguirà il confronto per voi.

esempio,

$ diff /tmp/oldList /tmp/newList 

consultare il link pagina di uomo al di sopra per ulteriori informazioni. Questo dovrebbe occuparsi della prima parte del tuo problema.

+1

mi limiterò a sottolineare che il comando 'diff' ha un numero ridicolo di opzioni per la formattazione l'uscita, che potrebbe fornire un ingresso conveniente per il programma che elaborerà le differenze. – chepner

+0

@chepner buon punto ... vale sicuramente la pena controllare la pagina man collegata. – Levon

0

Hai provato diff

$ diff /tmp/oldList /tmp/newList 

$ man diff 
2

Considerare l'utilizzo di Ruby se gli script richiedono una buona leggibilità.

Per ottenere le linee solo nel vecchio file:

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

Per ottenere le linee solo nel nuovo file:

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

è possibile alimentare che in un po 'di lettura ciclo per elaborare ogni line:

1

Questo è vecchio, ma per completezza dovremmo dire che se si dispone di un set veramente grande, le digiunanze soluzione t sarebbe quella di utilizzare diff per generare uno script e quindi fonte esso, in questo modo:

#!/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 

linee modificate appariranno come cancellati e aggiunti. Se non ti piace, puoi utilizzare il formato di gruppo invariato. Controlla la pagina del manuale di diff.