Verwenden Sie eine Liste von Wörtern, um in einer anderen Liste zu greifen

8

Ich habe eine Liste mit 250 Zeilen. Ich muss sie alle über einen Webserver ausführen, um eine Liste der Ausgaben zu erhalten. Diese Liste gibt jedoch viel mehr Zeilen zurück, als ich interessiert bin. Sagen wir, meine list.txtist:

a.1
b.1
etc

dann ist die Ausgabe output.txt:

a.1 a b c
a.2 b a b
a.3 d k o
b.1 b o p
b.2 o i y
b.3 p i y
etc

Ist es möglich, mit dem Befehl grep nach allen Wörtern in list.txt in der output.txt zu suchen und dann "die gewünschte" Liste want.txt zu generieren? Ich brauche die gesamte Zeile in meiner output.txt. Ich bin neu in der Skripterstellung, aber ich möchte etwas wie

grep list.txt output.txt > wanted.txt

Ich konnte keine Beispiele dafür finden

Ditte
quelle
Sind beide in alphabetischer Reihenfolge wie Ihre Beispiele?
Oli
Nein, ich habe eine bestimmte nicht alphabetische Reihenfolge in meiner list.txt, aber die output.txt ist alphabetisch, aber ich möchte, dass sie nur die "Treffer" für meine list.txt in derselben nicht alphabetischen Reihenfolge enthält
Ditte

Antworten:

11

Ich würde dies ignorieren grep. Es ist gut für reguläre Ausdrücke, aber es sieht nicht so aus, als ob Sie das hier wirklich brauchen. commkann zwei Dateien vergleichen und Ihnen Schnittpunkte anzeigen. Verwenden Sie Ihre genauen Beispiele:

$ comm -12 list.txt output.txt 
a.1
b.1
etc

Dies ist schneller als jeder Grep, hängt jedoch (stark) von den zu sortierenden Dateien ab. Wenn dies nicht der Fall ist, können Sie sie vorsortieren, dies ändert jedoch die Ausgabe, sodass sie auch sortiert wird.

comm -12 <(sort list.txt) <(sort output.txt) 

Alternativ diese Antwort von iiSeymour lassen Sie tun es mit grep. Die Flags fordern eine Eingabedatei an und erzwingen eine Suche mit festen Zeichenfolgen und vollständigen Wörtern. Dies hängt nicht von der Bestellung ab, sondern basiert auf der output.txtBestellung. Kehren Sie die Dateien um, wenn Sie sie in der Reihenfolge list.txt haben möchten.

$ grep -wFf list.txt output.txt 
a.1
b.1
etc

Wenn Ihr list.txtist wirklich groß, können Sie diese ein wenig mehr iterativ angehen müssen und jede Zeile passieren separat grep. Dies wird die Verarbeitungszeit massiv verlängern. Oben würden Sie einmal lesen output.txt, aber auf diese Weise würden Sie es für jede list.txt-Zeile lesen und verarbeiten. Es ist schrecklich ... Aber es könnte Ihre einzige Wahl sein. Auf der anderen Seite sortiert es dann die Dinge nach der list.txtReihenfolge.

$ while read line; do grep -wF "$line" output.txt; done < list.txt
a.1
b.1
etc
Oli
quelle
1
Das ist echt schlau! Was ist der Grund für die -12?
Ditte
3
-1unterdrückt Zeilen, die für die erste Datei -2eindeutig sind , unterdrückt Zeilen, die für die zweite Datei eindeutig sind, und -3unterdrückt Zeilen, die beiden gemeinsam sind. Um nur die gemeinsamen Linien zu erhalten, unterdrücken wir daher die Unikate -12.
Oli
nett! Ich denke, ich werde den Befehl comm verwenden. Und wenn ich dann die output.txt so sortieren möchte, dass sie dieselbe Reihenfolge wie list.txt hat, verwende ich danach einfach das Komm -12 <(sort list.txt) <(sort output.txt)?
Ditte
Der Befehl comm gab mir nicht die gesamte Zeile in der Datei result.txt (und ich brauche alles, um die Informationen von dort zu erhalten). Aber wenn ich den Befehl grep versuche, wird ich mit grep: out of memory aufgefordert. Heißt das, es ist zu groß?
Ditte
Das zweite Beispiel hat eine redundante STDIN-Umleitung, die die Shell als Fehler kennzeichnen würde. Erstellen Sie entweder temporäre Dateien oder verwenden Sie ein zusätzliches fd mit einer dazugehörigen Hintergrundsortierung (in den meisten Shells schwierig). Dies ist eher eine Programmierfrage, die bei Stack Overflow besser gestellt wird . persönlich würde ich das in Python machen.
Skaperen