GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Zeilen aus Textdatei auswählen, deren IDs in einer anderen Datei aufgeführt sind?

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

Linux
  1. Ersetzen Sie Linien, die einem Muster entsprechen, durch Linien aus einer anderen Datei in der richtigen Reihenfolge?

  2. Awk aus verschiedenen Linien?

  3. Erstellen Sie Text, der Daten aus einer Datei liest?

  4. Wie entferne ich Zeilenumbrüche aus einer Textdatei?

  5. Wie entferne ich die Zeilen, die in Datei B erscheinen, aus einer anderen Datei A?

So erstellen Sie Verzeichnisse aus einer Textdatei unter Linux

So drucken Sie doppelte Zeilen in einer Textdatei unter Linux

So löschen Sie Dateien, die in einer anderen Datei unter Linux aufgeführt sind

Wie wähle ich mehrere Zeilen aus einer Datei oder aus einer Pipe in einem Skript aus?

Wie wähle ich den gesamten Text aus einer Datei mit Nano aus?

Wie zeigt man bestimmte Zeilen aus einer Textdatei in Linux an?