Ich verwende viel grep awk sort in meiner Unix-Shell, um mit mittelgroßen (ca. 10M-100M Zeilen) tabulatorgetrennten Spaltentextdateien zu arbeiten. Insofern ist die Unix-Shell meine Tabellenkalkulation.
Aber ich habe ein riesiges Problem, nämlich das Auswählen von Datensätzen anhand einer Liste von IDs.
table.csv
haben Datei im Format idtfootbar...
und ids.csv
Datei mit Liste von IDs, wählen Sie nur Datensätze aus table.csv
mit ID in ids.csv
vorhanden .
Art von https://stackoverflow.com/questions/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-ids aber mit Shell, nicht perl.
grep -F
erzeugt offensichtlich falsch positive Ergebnisse, wenn IDs eine variable Breite haben.join
ist ein Dienstprogramm, das ich nie herausfinden konnte. Zunächst erfordert es eine alphabetische Sortierung (meine Dateien sind normalerweise numerisch sortiert), aber selbst dann bekomme ich es nicht zum Laufen, ohne mich über eine falsche Reihenfolge zu beschweren und einige Datensätze zu überspringen. Also ich mag es nicht.
grep -f gegen Datei mit ^idt
-s ist sehr langsam, wenn die Anzahl der IDs groß ist.awk
ist umständlich.
Gibt es dafür gute Lösungen? Irgendwelche speziellen Tools für tabulatorgetrennte Dateien? Zusätzliche Funktionen sind ebenfalls sehr willkommen.
UPD:sort
korrigiert -> join
Akzeptierte Antwort:
Ich schätze, Sie meinten grep -f
nicht grep -F
aber Sie brauchen tatsächlich eine Kombination aus beidem und -w
:
grep -Fwf ids.csv table.csv
Der Grund, warum Sie falsch positive Ergebnisse erhalten haben, ist (ich denke, Sie haben es nicht erklärt), weil, wenn eine ID in einer anderen enthalten sein kann, beide gedruckt werden. -w
beseitigt dieses Problem und -F
stellt sicher, dass Ihre Muster als Zeichenfolgen und nicht als reguläre Ausdrücke behandelt werden. Von man grep
:
-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.)
-w, --word-regexp
Select only those lines containing matches that form whole
words. The test is that the matching substring must either be
at the beginning of the line, or preceded by a non-word
constituent character. Similarly, it must be either at the end
of the line or followed by a non-word constituent character.
Word-constituent characters are letters, digits, and the
underscore.
-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.)
Wenn Ihre Fehlalarme darauf zurückzuführen sind, dass eine ID in einem Nicht-ID-Feld vorhanden sein kann, durchlaufen Sie stattdessen Ihre Datei:
while read pat; do grep -w "^$pat" table.csv; done < ids.csv
oder schneller:
xargs -I {} grep "^{}" table.csv < ids.csv
Ich persönlich würde das in perl
machen obwohl:
perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}}
print $_ if defined($k{$F[0]}); ' table.csv