Tool in Unix zum Subtrahieren von Textdateien?

16

Ich habe eine große Datei, die aus durch Semikolons getrennten Textfeldern in Form einer großen Tabelle besteht. Es wurde sortiert. Ich habe eine kleinere Datei, die aus denselben Textfeldern besteht. Irgendwann hat jemand diese Datei mit anderen verkettet und dann die oben beschriebene große Datei sortiert. Ich möchte die Zeilen der kleinen Datei von der großen subtrahieren (dh für jede Zeile in der kleinen Datei, wenn eine übereinstimmende Zeichenfolge in der großen Datei vorhanden ist, löschen Sie diese Zeile in der großen Datei).

Die Datei sieht ungefähr so ​​aus

GenericClass1; 1; 2; NA; 3; 4;
GenericClass1; 5; 6; NA; 7; 8;
GenericClass2; 1; 5; NA; 3; 8;
GenericClass2; 2; 6; NA; 4; 1;

etc

Gibt es eine schnelle klassische Möglichkeit, dies zu tun, oder muss ich awk verwenden?

Escher
quelle

Antworten:

28

Sie können verwenden grep. Geben Sie die kleine Datei als Eingabe ein und weisen Sie sie an, nicht übereinstimmende Zeilen zu finden:

grep -vxFf file.txt bigfile.txt > newbigfile.txt

Folgende Optionen werden verwendet:

   -F, --fixed-strings
          Interpret PATTERN as a  list  of  fixed  strings,  separated  by
          newlines,  any  of  which is to be matched.  (-F is specified by
          POSIX.)
   -f FILE, --file=FILE
          Obtain  patterns  from  FILE,  one  per  line.   The  empty file
          contains zero patterns, and therefore matches nothing.   (-f  is
          specified by POSIX.)

   -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v
          is specified by POSIX.)
   -x, --line-regexp
          Select only those matches that exactly match the whole line.  
          (-x is specified by POSIX.)
terdon
quelle
Schön, hat perfekt funktioniert. Vielen Dank.
Escher
1
Es ist cool, dass es funktioniert hat, aber es scheint mir, dass es mit dieser -xOption auch besser gewesen wäre, wenn mir eine Zeile in der kleineren Datei eine Teilzeichenfolge einer anderen Zeile in der Hauptdatei zugestoßen wäre. Es ist auch gut möglich, dass @ UlrichSchwarz schneller antwortet.
rici
18

comm ist dein Freund:

NAME comm - vergleicht zwei sortierte Dateien zeilenweise

SYNOPSIS comm [OPTION] ... FILE1 FILE2

BESCHREIBUNG Vergleichen Sie die sortierten Dateien FILE1 und FILE2 zeilenweise.

   With  no  options, produce three-column output.  Column one contains lines unique to FILE1, column two contains
   lines unique to FILE2, and column three contains lines common to both files.

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

( commhat wahrscheinlich einen Leistungsvorteil gegenübergrep da es die Sortierbarkeit berücksichtigt.)

Beispielsweise:

comm -1 -3 file.txt bigfile.txt > newbigfile.txt
Ulrich Schwarz
quelle
2
Guter Punkt über die Verwendung von Comm over Grep für sortierte Listen. Dies würde eine bessere Antwort, wenn Sie eine bestimmte Befehlszeile wie zB gabcomm -1 -3 file.txt bigfile.txt > newbigfile.txt
Steve Midgley
Ich bestätige, dass ich den oben angegebenen grep-Befehl mit Dateien um 100 MB ausprobiert habe und einen "getöteten" Fehler erhalten habe. Der Versuch mit comm wurde erfolgreich beendet.
Gianluca Casati
Die Befehlsumleitung ist nützlich für unsortierte Dateien oder wenn Sie mehr als zwei Dateien benötigen:comm -1 -3 <(sort BAD.txt GOOD.txt) <(sort FILES.txt)
odinho - Velmont