Grepping eines Teilstrings aus einem Grep-Ergebnis

11413
user17245

Bei einer Protokolldatei mache ich normalerweise so etwas:

grep 'marker-1234' filter_log 

Was ist der Unterschied, wenn Sie '' oder '' oder nichts im Muster verwenden?

Der obige Befehl grep wird viele tausend Zeilen ergeben. was ich wünsche Innerhalb dieser Zeilen gibt es normalerweise einen Teil der Daten, nach denen ich suche. Manchmal drucke ich mit awk die Felder aus, nach denen ich suche. In diesem Fall ändert sich das Protokollformat. Ich kann mich nicht ausschließlich auf die Position verlassen. Ganz zu schweigen davon, dass die tatsächlich protokollierten Daten die Position nach vorne schieben können.

Um dies verständlich zu machen, sagen wir, die Protokollzeile enthielt eine IP-Adresse, und das war alles, wonach ich gesucht hatte. Ich kann sie später sortieren, um eindeutig zu sein und einige Zählerstände zu erhalten.

Ein Beispiel kann sein:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: foo@bar.example.com to bar@foo.example.com [stat-xyz9876] 

Der erste grep-Befehl gibt mir viele tausend Zeilen wie oben, von dort möchte ich ihn wahrscheinlich an etwas weiterleiten sed, das ein Muster darin herausziehen und nur das Muster drucken kann.

In diesem Beispiel würde die Verwendung einer IP-Adresse ausreichen. Ich habe es versucht. Kann sed[0-9] nicht verstehen. als Muster Ich musste [0-9] [0-9] [0-9]. was zu seltsamen Ergebnissen führte, bis das gesamte Muster entstand.

Dies ist nicht spezifisch für eine IP-Adresse, das Muster ändert sich, aber ich kann es als Lernvorlage verwenden.

Danke euch allen.

4
Das hört sich sehr programmierungsbedingt an, auch einfache Bash-Befehle wie * grep * und * awk * werden meiner Meinung nach besser auf stackoverflow beantwortet. Josh K vor 14 Jahren 0
@Josh: SU hat viele Linux-Kommandozeilen-Krieger, die mit dieser Art von Fragen umgehen können, und das ist hier willkommen. Es könnte eine der Fragen sein, die auf beide Seiten passen würden, also liegt es wirklich am Fragesteller. quack quixote vor 14 Jahren 0
Ich dachte darüber nach, und um ehrlich zu sein, wusste ich nicht, wo ich es posten sollte. Ich ging mit dem Namen der Websites ein und stellte fest, dass SO allgemeiner ist und SU mehr Verwaltungssachen ist. Ich finde, die meisten schnellen Shell-Skripte beziehen sich auf Admin. Sicher, Sie kommen aus einem oder anderen Grund in große tcl- oder bash-Projekte, und in diesem Fall würde ich mich auf das Programmieren beschränken und bei SO posten. Dies war mehr ein Liner'ish und SU schien ein gutes Zuhause zu sein. Tut mir leid, wenn ich an der falschen Stelle gepostet habe, aber in manchen Fällen scheint es eine graue Fläche zu sein. user17245 vor 14 Jahren 0
@allentown: Serverfehler ist eigentlich mehr Admin-Typ-Sachen; Super User ist mehr Endbenutzerzeugnis. (aber Power-User-Endbenutzer.) Diese Frage ist auf jedem SO / SF / SU wahrscheinlich willkommen. Sie haben bereits eine Antwort akzeptiert. Wenn Sie zufrieden sind, können Sie sie als erledigt bezeichnen. oder wenn Sie möchten, können wir es nach SO / SF migrieren. kennzeichnen Sie es einfach für die Aufmerksamkeit des Moderators und teilen Sie uns mit, wohin es gesendet werden soll. Vielen Dank! quack quixote vor 14 Jahren 0
@quack: Das ist in Ordnung, ich dachte nur, dass eine bessere Antwort gefunden werden könnte, aber es scheint, als wäre sie schon gefunden worden. Josh K vor 14 Jahren 0

4 Antworten auf die Frage

7
Chris S

I don't know what OS you're on, but on FreeBSD 7.0+ grep has a -o option to return only the part that matches the pattern. So you could
grep "marker-1234" filter_log | grep -oE "[0-9]\.[0-9]\.[0-9]\.[0-9]"

Returns a list of just IP addresses from the 'filter_log"...

This works on my system, but again, I don't know what your version of grep supports.

Ich denke, alle Antworten hier sind ausgezeichnete Wege des Lernens und Annäherens an das Endergebnis mit derselben Antwort. Ich mag dieses besonders, da es leicht zu merken ist und nur mehrere grep-Befehle miteinander verkettet. Unter Mac OS X habe ich anscheinend die Option -o und benutze die Option -E natürlich schon oft. Danke für Ihre Antwort user17245 vor 14 Jahren 0
3
user31894

you can do all these in just one awk command. No need to use any other tools

$ awk '/marker-1234/ }' file (123.123.123.123) 
Danke, das klappt, awk kann dir manchmal ein bisschen weh tun, aber ich gewöhne mich an das für FOO ... ein Aspekt des schnellen Materials in der Schale. Sehr kraftvoll. user17245 vor 14 Jahren 0
2
Dennis Williamson

You can shorten the second grep a little like this:

grep -Eo '([0-9]\.)[0-9]' 

To answer your first question, double quotes allow the shell to do various things like variable expansion, but protect some metacharacters from needing to be escaped. Single quotes prevent the shell from doing those expansions. Using no quotes leaves things wide open.

$ empty="" $ text1="some words" $ grep $empty some_file (It seems to hang, but it's just waiting for input since it thinks "some_file" is the pattern and no filename was entered, so it thinks input is supposed to come from standard input. Press Ctrl-d to end it.) $ grep "$empty" some_file (The whole file is shown since a null pattern matches everything.) $ grep $text1 some_file grep: words: No such file or directory some_file:something some_file:some words (It sees the contents of the variable as two words, the first is seen as the pattern, the second as one file and the filename as a second file.) $ grep "$text1" some_file some_file:some words (Expected results.) $ grep '$text1' some_file (No results. The variable isn't expanded and the file doesn't contain a string that consists of literally those characters (a dollar sign followed by "text1")) 

You can learn more in the "QUOTING" section of man bash

Großartig, danke. Ich muss das auch mit regad zu IFS besser in den Griff bekommen, ich war neulich ziemlich aufgehängt, habe es aber geschafft, IFS dazu zu bringen, nett zu spielen. Es ist eine schreckliche Sache, wenn Sie IFS eingestellt haben und es vergessen haben, und ich frage mich, dass wtf eine Stunde lang läuft. user17245 vor 14 Jahren 0
Es ist eine gute Idee, die Gewohnheit zu haben, den Wert von `IFS` immer zu speichern und so schnell wie möglich wiederherzustellen:` saveIFS = "$ IFS"; IFS = ","; etwas tun; IFS = "$ saveIFS"; do_other_stuff` Dennis Williamson vor 14 Jahren 0
+1 Guter Aufruf zum Regex, ich benutze ihn nicht sehr oft, daher bin ich ein bisschen ineffizient. Chris S vor 14 Jahren 0
1
Jennifer

Look up the xargs command. You should be able to do something like:

grep 'marker-1234' filter_log|xargs grep "("|cut -c1-15

This may not be it exactly, but xargs is the command you want to use