Die Antwort von Costas ist angesichts Ihres genauen Problems wahrscheinlich die beste, da Sie ein Feld haben, das zu 100% übereinstimmt.
Aber wenn Ihr Problem wirklich war für Millionen von regexps in Milliarden von Zeilen greppen, dann hat GNU Parallel eine Beschreibung, wie das zu tun: https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Grepping -n-Zeilen-für-m-reguläre-Ausdrücke
Die einfachste Lösung, um eine große Datei für viele reguläre Ausdrücke zu durchsuchen, ist:
grep -f regexps.txt bigfile
Oder wenn die regulären Ausdrücke feste Zeichenfolgen sind:
grep -F -f regexps.txt bigfile
Es gibt drei einschränkende Faktoren: CPU, RAM und Festplatten-E / A.
RAM ist einfach zu messen: Wenn der grep-Prozess den größten Teil Ihres freien Speichers beansprucht (z. B. wenn Sie oben ausgeführt werden), ist RAM ein begrenzender Faktor.
Die CPU ist auch leicht zu messen: Wenn der grep> 90% der CPU oben einnimmt, ist die CPU ein begrenzender Faktor, und die Parallelisierung beschleunigt dies.
Es ist schwieriger zu erkennen, ob die Festplatten-E / A der begrenzende Faktor ist, und je nach Festplattensystem kann die Parallelisierung schneller oder langsamer sein. Der einzige Weg, um sicher zu wissen, ist zu testen und zu messen.
Begrenzungsfaktor: RAM
Die normale grep -f regexs.txt-Bigfile funktioniert unabhängig von der Größe der Bigfile. Wenn die regexps.txt jedoch so groß ist, dass sie nicht in den Speicher passt, müssen Sie sie aufteilen.
grep -F benötigt ungefähr 100 Bytes RAM und grep ungefähr 500 Bytes RAM pro 1 Byte Regexp. Wenn also regexps.txt 1% Ihres Arbeitsspeichers ausmacht, ist es möglicherweise zu groß.
Wenn Sie Ihre regulären Ausdrücke in feste Zeichenfolgen konvertieren können, tun Sie dies. ZB wenn die Zeilen, nach denen Sie in bigfile suchen, alle so aussehen:
ID1 foo bar baz Identifier1 quux
fubar ID2 foo bar baz Identifier2
dann kann Ihre regexps.txt konvertiert werden von:
ID1.*Identifier1
ID2.*Identifier2
in:
ID1 foo bar baz Identifier1
ID2 foo bar baz Identifier2
Auf diese Weise können Sie grep -F verwenden, das etwa 80% weniger Speicher benötigt und viel schneller ist.
Wenn es immer noch nicht in den Speicher passt, können Sie dies tun:
parallel --pipepart -a regexps.txt --block 1M grep -F -f - -n bigfile |
sort -un | perl -pe 's/^\d+://'
Die 1M sollte Ihr freier Speicher sein, geteilt durch die Anzahl der Kerne und geteilt durch 200 für grep -F und durch 1000 für normales grep. Unter GNU / Linux können Sie Folgendes tun:
free=$(awk '/^((Swap)?Cached|MemFree|Buffers):/ { sum += $2 }
END { print sum }' /proc/meminfo)
percpu=$((free / 200 / $(parallel --number-of-cores)))k
parallel --pipepart -a regexps.txt --block $percpu --compress grep -F -f - -n bigfile |
sort -un | perl -pe 's/^\d+://'
Wenn Sie mit doppelten Zeilen und falscher Reihenfolge leben können, ist dies schneller:
parallel --pipepart -a regexps.txt --block $percpu --compress grep -F -f - bigfile
Begrenzungsfaktor: CPU
Wenn die CPU der begrenzende Faktor ist, sollte die Parallelisierung auf den regulären Ausdrücken erfolgen:
cat regexp.txt | parallel --pipe -L1000 --round-robin --compress grep -f - -n bigfile |
sort -un | perl -pe 's/^\d+://'
Der Befehl startet einen Grep pro CPU und liest Bigfile einmal pro CPU. Da dies jedoch parallel erfolgt, werden alle Lesevorgänge mit Ausnahme des ersten im RAM zwischengespeichert. Abhängig von der Größe von regexp.txt ist es möglicherweise schneller, --block 10m anstelle von -L1000 zu verwenden.
Einige Speichersysteme bieten eine bessere Leistung, wenn mehrere Blöcke gleichzeitig gelesen werden. Dies gilt für einige RAID-Systeme und für einige Netzwerkdateisysteme. Um das Lesen von Bigfile zu parallelisieren:
parallel --pipepart --block 100M -a bigfile -k --compress grep -f regexp.txt
Dadurch wird bigfile in 100-MB-Blöcke aufgeteilt und grep für jeden dieser Blöcke ausgeführt. Um sowohl das Lesen von bigfile als auch von regexp.txt zu parallelisieren, kombinieren Sie beide mit --fifo:
parallel --pipepart --block 100M -a bigfile --fifo cat regexp.txt \
\| parallel --pipe -L1000 --round-robin grep -f - {}
Wenn eine Zeile mit mehreren regulären Ausdrücken übereinstimmt, wird die Zeile möglicherweise dupliziert.
Größeres Problem
Wenn das Problem zu groß ist, um damit gelöst zu werden, sind Sie wahrscheinlich bereit für Lucene.