Ich habe diff ausprobiert, aber es werden einige Zahlen und andere Symbole vor verschiedenen Zeilen generiert, was mir den Vergleich von Dateien erschwert.
So
Antworten:
215
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).
Denken Sie daran , dass zwei Dateien sortiert werden müssen und ist einzigartig
andy
6
Sie können die Optionen zusammenfassen:comm -23
Paolo M
Was bedeutet "sortiert"? Dass die Zeilen die gleiche Reihenfolge haben? Dann ist es wahrscheinlich für die meisten Anwendungsfälle in Ordnung - wie in der Überprüfung, welche Zeilen hinzugefügt wurden, indem Sie sie mit einer gesicherten älteren Version vergleichen. Wenn neu hinzugefügte Zeilen nicht zwischen den vorhandenen Zeilen liegen können, ist dies eher ein Problem.
Egor Hans
@EgorHans: Wenn die Datei zB Zeilen enthält, die Ganzzahlen wie "3 \ n1 \ n3 \ n2 \ n" enthalten, müssen die Zeilen zuerst in aufsteigender oder absteigender Reihenfolge neu angeordnet werden, z. B. "\ 1 \ n2 \ n3 \ n3 \ n" mit Duplikaten benachbart. Das ist "sortiert" und beide Dateien müssen auf ähnliche Weise sortiert werden. Wenn die neuere Datei neue Zeilen enthält, spielt es keine Rolle, ob sie "zwischen vorhandenen Zeilen" liegen, da sie nach der Sortierung nicht in sortierter Reihenfolge angezeigt werden.
Sorpigal
47
Das Unix-Dienstprogramm diffist genau für diesen Zweck gedacht.
$ diff -u file1 file2 > file3
Optionen, verschiedene Ausgabeformate usw. finden Sie im Handbuch und im Internet.
Das macht den angeforderten Job nicht; Es werden eine Reihe zusätzlicher Zeichen eingefügt, selbst wenn Befehlszeilenschalter verwendet werden, die in anderen Antworten vorgeschlagen werden.
Xenocyon
20
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."
Diese Antwort unterliegt zwei Einschränkungen: (1) Sie funktioniert nur für kurze Zeilen (standardmäßig weniger als 80 Zeichen, obwohl dies geändert werden kann), und, was noch wichtiger ist, (2) am Ende wird jeweils ein "<" hinzugefügt Zeile, die mit einem anderen Programm entfernt werden muss (z. B. awk, sed).
Sergut
In vielen Fällen möchten Sie auch verwenden -d, diffum das kleinstmögliche Diff zu finden. -i, -E, -w, -BUnd --suppress-blank-emptykann auch gelegentlich nützlich, wenn auch nicht immer sein. Wenn Sie nicht wissen, was zu Ihrem Anwendungsfall passt, versuchen Sie es diff --helpzuerst (was im Allgemeinen eine gute Idee ist, wenn Sie nicht wissen, was ein Befehl tun kann).
Egor Hans
Wenn Sie --line-format =% L verwenden, verhindern Sie außerdem, dass diff zusätzliche Zeichen generiert (zumindest heißt es in der Hilfe, dass dies so funktioniert, Sie es jedoch gleich ausprobieren werden).
Manchmal diffist das Dienstprogramm, das Sie benötigen, aber manchmal joinist 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.
Sie sollten eine Medaille dafür bekommen! Es war genau das, wonach ich in den letzten 2 Stunden
gesucht habe
7
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).
Nettes Dienstprogramm! Ich liebe es, wie es die Unterscheidungslinien markiert. Erleichtert den Vergleich von Konfigurationen erheblich. Dies zusammen mit sort ist eine tödliche Kombination (zB sdiff <(sort file1) <(sort file2))
jmagnusson
3
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 commweder grep -Fnoch 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, grepund 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:
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.
comm erfordert keine Sortierung (in neueren Versionen?) - verwenden Sie einfach --nocheck-order. Ich benutze dies oft, wenn ich CSVs von der CLI aus manipuliere
ak5
2
Ich bin überrascht, dass niemand erwähnt hat diff -y, dass er nebeneinander ausgegeben werden soll , zum Beispiel:
diff -y file1 file2 > file3
Und in file3(verschiedene Zeilen haben ein Symbol |in der Mitte):
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 .
Das ist eine schlechte Idee. Sie müssten auch Zeilen ändern, die mit beginnen <. Sie sehen dies, wenn Sie die Reihenfolge der Eingabedateien vertauschen. Selbst wenn Sie dies tun würden, würden Sie es grepmit 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'.
Sorpigal
0
Sie können diffmit folgenden Ausgabeformatierungen verwenden:
--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.
Antworten:
diff (1) ist nicht die Antwort, aber comm (1) ist.
So
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 ...
vorausgesetzt, Ihre Shell unterstützt die Prozessersetzung (bash tut dies).
quelle
comm -23
Das Unix-Dienstprogramm
diff
ist genau für diesen Zweck gedacht.Optionen, verschiedene Ausgabeformate usw. finden Sie im Handbuch und im Internet.
quelle
Betrachten Sie diese:
Datei a.txt:
Datei b.txt:
Sie können den Unterschied finden mit:
Die Ausgabe wird sein:
Sie können die Ausgabe in einer Ausgabedatei (c.txt) umleiten, indem Sie:
Dies wird Ihre Frage beantworten:
quelle
-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 esdiff --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 manchmaljoin
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.quelle
Versuchen
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,
quelle
sdiff <(sort file1) <(sort file2)
)Wenn Sie dies mit Coreutils lösen müssen, ist die akzeptierte Antwort gut:
Sie können auch sd (stream diff) verwenden, das weder sortiert noch ersetzt werden muss und unendliche Streams unterstützt, wie z.
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
wedergrep -F
noch verwendendiff
.Hier ist ein Blogpost, den ich über unterschiedliche Streams auf dem Terminal geschrieben habe und in dem sd vorgestellt wird.
quelle
Noch keine
grep
Lösung?Zeilen, die nur in Datei2 vorhanden sind:
Zeilen, die nur in Datei1 vorhanden sind:
Zeilen, die in beiden Dateien vorhanden sind:
quelle
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
undawk
(oder ähnliches).Wenn die Zeilen kein "<" enthalten, kann ein kurzer Einzeiler sein:
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:
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.
quelle
Ich bin überrascht, dass niemand erwähnt hat
diff -y
, dass er nebeneinander ausgegeben werden soll , zum Beispiel:Und in
file3
(verschiedene Zeilen haben ein Symbol|
in der Mitte):quelle
Verwenden Sie das Dienstprogramm Diff und extrahieren Sie nur die Zeilen, die in der Ausgabe mit <beginnen
quelle
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 .
quelle
<
. Sie sehen dies, wenn Sie die Reihenfolge der Eingabedateien vertauschen. Selbst wenn Sie dies tun würden, würden Sie esgrep
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:--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.quelle