Ich habe eine Datei f1
:
line1
line2
line3
line4
..
..
Ich möchte alle Zeilen löschen, die sich in einer anderen Datei befinden f2
:
line2
line8
..
..
Ich habe etwas mit cat
und ausprobiert sed
, was nicht einmal dem entsprach, was ich beabsichtigt hatte. Wie kann ich das machen?
Antworten:
grep -v -x -f f2 f1
sollte den Trick machen.Erläuterung:
-v
nicht übereinstimmende Zeilen auswählen-x
nur ganze Zeilen abgleichen-f f2
Muster von bekommenf2
Man kann stattdessen verwenden
grep -F
oderfgrep
passen feste Strings vonf2
eher als Muster (im Fall , dass Sie die Zeilen in einer entfernen „ was Sie sehen , ob das, was man bekommt“ Art und Weise , anstatt die Linien bei der Behandlungf2
als regex Muster).quelle
grep
. Wenn esf2
vor Beginn der Suche ordnungsgemäß vorverarbeitet wird, dauert die Suche nur O (n) Zeit.Versuchen Sie stattdessen comm (vorausgesetzt, f1 und f2 sind "bereits sortiert")
quelle
comm
die Lösung die Frage hat, dass die Zeilenf1
nicht sortiert sind, was eine Voraussetzung für die Verwendung istcomm
comm -2 -3 <(sort f1) <(sort f2)
Um nicht zu große Dateien auszuschließen, können Sie die assoziativen Arrays von AWK verwenden.
Die Ausgabe erfolgt in derselben Reihenfolge wie die Datei "from-this.txt". Die
tolower()
Funktion macht es unabhängig von Groß- und Kleinschreibung, wenn Sie das brauchen.Die algorithmische Komplexität wird wahrscheinlich O (n) (Größe von exclude-this.txt) + O (n) (Größe von-this.txt) sein.
quelle
exclude-these.txt
es leer ist. Die Antwort von @ jona-christopher-sahnwaldt unten funktioniert in diesem Fall. Sie können auch mehrere Dateien angeben, z. B.awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 done.out failed.out f=2 all-files.out
Ähnlich wie bei Dennis Williamsons Antwort (meistens syntaktische Änderungen, z. B. explizite Einstellung der Dateinummer anstelle des
NR == FNR
Tricks):awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 exclude-these.txt f=2 from-this.txt
Durch den Zugriff
r[$0]
wird der Eintrag für diese Zeile erstellt, ohne dass ein Wert festgelegt werden muss.Unter der Annahme, dass awk eine Hash-Tabelle mit konstanter Suche und (im Durchschnitt) konstanter Aktualisierungszeit verwendet, beträgt die zeitliche Komplexität O (n + m), wobei n und m die Länge der Dateien sind. In meinem Fall betrug n ~ 25 Millionen und m ~ 14000. Die awk-Lösung war viel schneller als sortieren, und ich zog es auch vor, die ursprüngliche Reihenfolge beizubehalten.
quelle
f
klarer alsNR == FNR
, aber das ist Geschmackssache. Die Zuweisung zum Hash sollte so schnell erfolgen, dass zwischen den beiden Versionen kein messbarer Geschwindigkeitsunterschied besteht. Ich glaube, ich habe mich in Bezug auf die Komplexität geirrt. Wenn die Suche konstant ist, sollte auch die Aktualisierung (im Durchschnitt) konstant sein. Ich weiß nicht, warum ich dachte, das Update wäre logarithmisch. Ich werde meine Antwort bearbeiten.awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 empty.file done.out failed.out f=2 all-files.out
. Während die andereawk
Lösung mit einer leeren Ausschlussdatei fehlschlägt und nur eine nehmen kann.wenn Sie Ruby haben (1.9+)
Welches hat O (N ^ 2) Komplexität. Wenn Sie sich für die Leistung interessieren, finden Sie hier eine andere Version
Dies verwendet einen Hash, um die Subtraktion zu bewirken, ebenso wie die Komplexität O (n) (Größe von a) + O (n) (Größe von b).
Hier ist ein kleiner Benchmark mit freundlicher Genehmigung von Benutzer 576875, jedoch mit 100.000 Zeilen, der oben genannten:
diff
wurde verwendet, um zu zeigen, dass es keine Unterschiede zwischen den 2 generierten Dateien gibt.quelle
Einige zeitliche Vergleiche zwischen verschiedenen anderen Antworten:
sort f1 f2 | uniq -u
ist nicht einmal ein symmetrischer Unterschied, da dadurch Zeilen entfernt werden, die in beiden Dateien mehrmals vorkommen.comm kann auch mit stdin und hier Strings verwendet werden:
quelle
Scheint ein Job zu sein, der für die SQLite-Shell geeignet ist:
quelle
Hast du das mit sed versucht ?
quelle
Keine 'Programmier'-Antwort, aber hier ist eine schnelle und schmutzige Lösung: Gehen Sie einfach zu http://www.listdiff.com/compare-2-lists-difference-tool .
Funktioniert natürlich nicht für große Dateien, aber es hat den Trick für mich getan. Ein paar Anmerkungen:
quelle