cat file_1
my colour is red
my rose is red
my colour is blue
my rose id blue
cat file_2
red
blue
cat output_file should be
my colour is red
my colour is blue
hier verwende ich
cat file_2 | while read line;do cat file_1 | grep "$line" | head -1;done
hier versuche ich, die oberste Zeile zu erhalten, die das enthält, pattern "red" and "blue"
was in der vorhanden istfile_2
Gibt es eine andere Möglichkeit, dies zu tun? as fast as possible
Die While-Schleife braucht Zeit
Antwort1
Sie können eine while
Konstruktion verwenden, um die Muster von zu durchlaufen file2
und dann -m 1
with verwenden grep
, um nach der ersten Übereinstimmung anzuhalten file1
:
while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
-F
behandelt das Muster wörtlich-m 1
bewirktgrep
das Beenden nach dem ersten Spiel
Shell-Schleifen sind normalerweise nicht effizient, aber da die Musterliste klein ist, sind sie in diesem Fall verwendbar.
Schnellere Alternative, xargs
:
xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
Verwenden Sie mehr parallele Prozesse ( -P
) für mehr Muster.
Beispiel:
% while IFS= read -r i; do grep -Fm1 "$i" file1; done <file2
my colour is red
my colour is blue
% xargs -a file2 -n1 -P2 -I'{}' grep -Fm1 {} file1
my colour is blue
my colour is red
Antwort2
So drucken Sie die erste Zeile aus Datei_1, die mit einer Zeile in Datei_2 übereinstimmt:
$ awk 'FNR==NR{a[$0];next} {for (line in a) if ($0~line) {print; delete a[line]}}' file_2 file_1
my colour is red
my colour is blue
Bei diesem Ansatz wird jede Datei nur einmal durchgelesen.
Wie es funktioniert
FNR==NR{a[$0];next}
Dadurch wird jede Zeile in Datei_2 als Schlüssel im assoziativen Array gespeichert
a
.for (line in a) if ($0~line) {print; delete a[line]}
Für jede Zeile in file_1 prüfen wir, ob sie mit einem Schlüssel im Array übereinstimmt
a
. Wenn dies der Fall ist, drucken wir die Zeile und löschen den Schlüssel.