2012-06-22 1 views
19

Ok, ich habe zwei ähnliche Listen auf meiner Linux-Box in Textdateien:Bash - Unterschied zwischen zwei Listen

/tmp/oldList 
/tmp/newList 

ich diese Listen vergleichen muß, um zu sehen, welche Zeilen hinzugefügt wurden und welche Linien wurden entfernt. Ich muss dann diese Zeilen durchlaufen und Aktionen ausführen, je nachdem, ob sie hinzugefügt oder entfernt wurden. Wie mache ich das in bash?

+0

Die gleiche Frage wurde 4 Tage vor http://stackoverflow.com/questions/11099894/comparing-2-unsorted-lists-in-linux-listing-the-unique-in-the-second-file/11101143 gestellt # 11101143 –

Antwort

50

Verwenden Sie den Befehl comm(1) die beiden Dateien zu vergleichen. Sie beide müssen sortiert werden, was Sie vorher tun können, wenn sie groß sind, oder Sie können es inline mit Bash Prozesssubstitution tun.

comm kann eine Kombination der Flags nehmen -1, -2 und -3 anzeigt, welche Datei von Linien zu unterdrücken (unique 1, einzigartig in Datei 2 oder beide gemeinsam zur Datei).

Um die Linien nur in der alten Datei zu erhalten:

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

Um die Linien nur in der neuen Datei zu erhalten:

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

Sie können das in eine while read Schleife füttern jede Zeile zu verarbeiten :

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

und ähnlich für die neuen Zeilen.

4

Die diff command wird den Vergleich für Sie tun.

z.B.

$ diff /tmp/oldList /tmp/newList 

die oben Mann-Link für weitere Informationen. Dies sollte sich um Ihren ersten Teil Ihres Problems kümmern.

+1

Ich betone nur, dass der 'diff' Befehl eine lächerliche Anzahl von Optionen zum Formatieren der Ausgabe hat, die eine bequeme Eingabe für das Programm liefern könnte, das die Unterschiede verarbeiten wird. – chepner

+0

@chepner guter Punkt .. es lohnt sich auf jeden Fall die verlinkte Man Seite zu überprüfen. – Levon

0

Haben Sie diff versucht

$ diff /tmp/oldList /tmp/newList 

$ man diff 
2

Verwenden Sie Ruby, wenn Ihre Skripte lesbar sind.

Um die Linien nur in der alten Datei zu erhalten:

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

Um die Linien nur in der neuen Datei zu erhalten:

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

Sie können das in eine Zeit lang füttern Schleife lesen jeweils zu verarbeiten line:

1

Das ist alt, aber der Vollständigkeit halber sollten wir sagen, dass wenn Sie ein wirklich großes Set haben, das schnellste t-Lösung wäre diff zu verwenden, um ein Skript zu generieren und dann beziehen, wie folgt aus:

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

geänderte Zeilen werden als gelöscht angezeigt und hinzugefügt. Wenn Ihnen das nicht gefällt, können Sie das --changed-group-format verwenden. Überprüfen Sie die manuelle Diff-Seite.