Grep mehrere Muster negative Übereinstimmung

14

Daher habe ich eine Reihe von Apache-Protokollen mit dem Standardprotokollformat. Ich möchte alle Protokollzeilen abrufen, die nicht von einem Webcrawler stammen.

Nehmen wir also an, ich habe eine Datei robot_patterns mit Einträgen wie

Googlebot
msnbot-media
YandexBot
bingbot

Wenn ich den Befehl ausführe grep -f robot_patterns *.log, erhalte ich alle Einträge von Bots, die den obigen Mustern entsprechen. Meine aktuelle Liste enthält ca. 30 Einträge von Bots und Agenten, die ich ignorieren möchte.

Aber ich möchte alle Einträge finden, die NICHT von Bots stammen . Also versuche ich grep -v -f robot_patterns *.logund es werden keine Ergebnisse von grep zurückgegeben. Dies ist nicht das, was ich erwarte oder wünsche, und ich finde keinen offensichtlichen Weg, um das zu bekommen, was ich will. Wenn Sie die -vOption mit mehreren Mustern in einer Datei kombinieren, gibt grep nur dann eine übereinstimmende Zeile zurück, wenn sie mit JEDEM Muster übereinstimmt.

Zoredache
quelle
Als ich dies auf meinem System versuchte, hatte grep -v -f das gewünschte Verhalten und gab nur Zeilen zurück, die keinem der Muster entsprachen. Dies war mit (GNU grep) 2.14.56-1e3d. Welches grep benutzt du?
Wingedsubmariner
Ich renne GNU grep 2.6.3.
Zoredache
4
Ich habe weitere Tests durchgeführt und festgestellt, dass eine leere Zeile in der Musterdatei mit jeder Zeile übereinstimmt, sodass mit -v keine Zeilen zurückgegeben werden. Dies ist jedoch kein Problem mit -F, und -F beschleunigt möglicherweise die Suche nach Ihrer Aufgabe - ist möglicherweise einen Versuch wert.
Wingedsubmariner
Eine nachgestellte leere Zeile! Argh ... Das scheint das Problem zu sein. Wenn Sie möchten, sollten Sie dies als Antwort hinzufügen.
Zoredache

Antworten:

8

Befindet sich eine leere Zeile in der Musterdatei, stimmt diese mit jeder Zeile überein, sodass keine Zeilen mit zurückgegeben werden -v. Dies liegt daran, dass die Zeilen als reguläre Ausdrücke interpretiert werden und ein leerer regulärer Ausdruck immer übereinstimmt.

Dies ist jedoch kein Problem -F, da grepLeerzeilen mit ignoriert werden -F.
-FVerursacht grep, dass die Zeilen als einfache Zeichenfolgen interpretiert werden, nach denen gesucht werden muss, und beschleunigt sich möglicherweise, grepwenn reguläre Ausdrücke nicht benötigt werden.

wingedsubmariner
quelle
1
GNU fgrepignorierte diese leere Zeichenkette als Fehler, der in 2.19 behoben wurde ( commit 2d3832e1ff772dc1a374bfad5dcc1338350cc48b , also sollten Sie sich nicht darauf verlassen.
Stéphane Chazelas
13

Du kannst es versuchen:

grep -vE 'Googlebot|msnbot-media|YandexBot|bingbot' yourlogfile
Orsius
quelle
2
Willkommen bei Unix & Linux. Das OP verfügt über eine Liste mit ungefähr 30 Zeichenfolgen, die ignoriert werden sollen, und die vier, die er als Beispiele vorgestellt hat, haben eine durchschnittliche Länge von jeweils zehn Zeichen, sodass Ihr Befehl wahrscheinlich mehr als 300 Zeichen lang ist. Dies ist wahrscheinlich schwer zu pflegen (und sogar zu lesen). Können Sie Ihre Antwort so ändern, dass sie von der Liste der Zeichenfolgen im OP abhängt? ………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………… - Das OP hat gelernt, wie man seinen ursprünglichen Arbeitsansatz erreicht.
G-Man sagt, dass Monica
2
Warum meine Antwort negativ bewerten? : /
Orsius
3
Gute Antwort. Hat Regex OR und die Option -vE war hilfreich.
Kirt Carson
3
Dies ist die Antwort auf die Frage, die die meisten Menschen wahrscheinlich zu lösen versuchen.
Perfi