Ich möchte Datei1 mit Datei2 vergleichen und eine Datei3 generieren, die die Zeilen in Datei1 enthält, die in Datei2 nicht vorhanden sind.
Ich möchte Datei1 mit Datei2 vergleichen und eine Datei3 generieren, die die Zeilen in Datei1 enthält, die in Datei2 nicht vorhanden sind.
Antworten:
diff (1) ist nicht die Antwort, aber comm (1) ist.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
So
comm -2 -3 file1 file2 > file3
Die Eingabedateien müssen sortiert werden. Wenn dies nicht der Fall ist, sortieren Sie sie zuerst. Dies kann mit einer temporären Datei erfolgen oder ...
comm -2 -3 <(sort file1) <(sort file2) > file3
vorausgesetzt, Ihre Shell unterstützt die Prozessersetzung (bash tut dies).
comm -23
Das Unix-Dienstprogramm diff
ist genau für diesen Zweck gedacht.
$ diff -u file1 file2 > file3
Optionen, verschiedene Ausgabeformate usw. finden Sie im Handbuch und im Internet.
Betrachten Sie diese:
Datei a.txt:
abcd
efgh
Datei b.txt:
abcd
Sie können den Unterschied finden mit:
diff -a --suppress-common-lines -y a.txt b.txt
Die Ausgabe wird sein:
efgh
Sie können die Ausgabe in einer Ausgabedatei (c.txt) umleiten, indem Sie:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Dies wird Ihre Frage beantworten:
"... die die Zeilen in Datei1 enthält, die in Datei2 nicht vorhanden sind."
-d
, diff
um das kleinstmögliche Diff zu finden. -i
, -E
, -w
, -B
Und --suppress-blank-empty
kann auch gelegentlich nützlich, wenn auch nicht immer sein. Wenn Sie nicht wissen, was zu Ihrem Anwendungsfall passt, versuchen Sie es diff --help
zuerst (was im Allgemeinen eine gute Idee ist, wenn Sie nicht wissen, was ein Befehl tun kann).
Manchmal diff
ist das Dienstprogramm, das Sie benötigen, aber manchmal join
ist es angemessener. Die Dateien müssen vorsortiert sein. Wenn Sie eine Shell verwenden, die die Prozessersetzung wie bash, ksh oder zsh unterstützt, können Sie die Sortierung im laufenden Betrieb durchführen.
join -v 1 <(sort file1) <(sort file2)
Versuchen
sdiff file1 file2
Normalerweise funktioniert es bei mir in den meisten Fällen viel besser. Möglicherweise möchten Sie Dateien vorher sortieren, wenn die Reihenfolge der Zeilen nicht wichtig ist (z. B. einige Textkonfigurationsdateien).
Beispielsweise,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Wenn Sie dies mit Coreutils lösen müssen, ist die akzeptierte Antwort gut:
comm -23 <(sort file1) <(sort file2) > file3
Sie können auch sd (stream diff) verwenden, das weder sortiert noch ersetzt werden muss und unendliche Streams unterstützt, wie z.
cat file1 | sd 'cat file2' > file3
Wahrscheinlich kein so großer Vorteil für dieses Beispiel, aber denken Sie trotzdem darüber nach. In einigen Fällen können Sie comm
weder grep -F
noch verwenden diff
.
Hier ist ein Blogpost, den ich über unterschiedliche Streams auf dem Terminal geschrieben habe und in dem sd vorgestellt wird.
Viele Antworten bereits, aber keine von ihnen perfekt IMHO. Die Antwort von Thanatos hinterlässt einige zusätzliche Zeichen pro Zeile und die Antwort von Sorpigal erfordert, dass die Dateien sortiert oder vorsortiert werden, was möglicherweise nicht unter allen Umständen angemessen ist.
Ich denke , der beste Weg , um die Linien zu bekommen , die sonst anders und nichts sind (keine zusätzlichen Zeichen, keine Nachbestellung) ist eine Kombination aus diff
, grep
und awk
(oder ähnliches).
Wenn die Zeilen kein "<" enthalten, kann ein kurzer Einzeiler sein:
diff urls.txt* | grep "<" | sed 's/< //g'
Dadurch wird jedoch jede Instanz von "<" (weniger als Leerzeichen) aus den Zeilen entfernt, was nicht immer in Ordnung ist (z. B. Quellcode). Die sicherste Option ist die Verwendung von awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Dieser Einzeiler unterscheidet beide Dateien, filtert dann die Ausgabe von diff im ed-Stil heraus und entfernt dann das nachfolgende "<", das diff hinzufügt. Dies funktioniert auch dann, wenn die Zeilen selbst ein "<" enthalten.
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
Ich habe fast alle Antworten in diesem Thread ausprobiert, aber keine war vollständig. Nach ein paar Trails oben hat einer für mich gearbeitet. Diff gibt Ihnen einen Unterschied, aber mit einigen unerwünschten speziellen Charas. wo Sie tatsächliche Differenzlinien beginnen mit '>'. Der nächste Schritt besteht darin, die Zeilen mit '>' zu erfassen und anschließend mit sed zu entfernen .
<
. Sie sehen dies, wenn Sie die Reihenfolge der Eingabedateien vertauschen. Selbst wenn Sie dies tun würden, würden Sie es grep
mit mehr sed weglassen wollen : `diff a1 a2 | sed '/> / s ///' `Dies kann immer noch Zeilen mit >
oder <
in der richtigen Situation unterbrechen und es bleiben zusätzliche Zeilen übrig, die die Zeilennummern beschreiben. Wenn Sie diesen Ansatz ausprobieren möchten, wäre ein besserer Weg : diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.
Sie können diff
mit folgenden Ausgabeformatierungen verwenden:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
Deaktivieren Sie die Ausgabe für Datei1, wenn die Zeile unterschiedlich war. Vergleichen Sie sie in Datei2.
--unchanged-line-format=''
Deaktivieren Sie die Ausgabe, wenn die Zeilen identisch sind.