Frage grepping einer Teilzeichenfolge aus einem grep-Ergebnis


Bei einer Protokolldatei werde ich normalerweise Folgendes tun:

grep 'marker-1234' filter_log

Was ist der Unterschied bei der Verwendung von "" oder "" oder nichts im Muster?

Der obige Befehl grep ergibt viele tausend Zeilen. was ich begehre. Innerhalb dieser Zeilen gibt es normalerweise einen Datenblock, nach dem ich suche. Manchmal benutze ich awk, um die Felder auszudrucken, 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 geloggten Daten die Position vorwärts drücken können.

Um das verständlich zu machen, nehmen wir an, dass die Log-Zeile eine IP-Adresse enthielt, und das war alles, was ich suchte, damit ich sie später sortieren und eindeutig machen und einige Zählungen erhalten kann.

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 wird mir viele tausend Zeilen wie oben geben, von da an möchte ich ihn wahrscheinlich an etwas weiterleiten sed, die ein Muster herausziehen und nur das Muster drucken kann.

Für dieses Beispiel würde die Verwendung einer IP-Adresse ausreichen. Ich habe es versucht. Ist sed nicht in der Lage [0-9] {1,3} zu verstehen. als ein Muster? Ich musste [0-9] [0-9] [0-9]. was zu seltsamen Ergebnissen führte, bis das gesamte Muster erstellt wurde.

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

Danke euch allen.


4
2018-04-09 01:18


Ursprung


Das klingt sehr programmierbezogen, sogar einfache Bash-Befehle mögen Grep und awk sind meiner Meinung nach besser auf stackoverflow beantwortet. - Josh K
@Josh: SU hat viele Linux-Kommandozeilen-Krieger, die mit dieser Art von Frage umgehen können, und es ist hier willkommen. Es könnte eine dieser Fragen sein, die zu beiden Seiten passen würden, also liegt es wirklich am Fragesteller. - quack quixote
Ich habe darüber nachgedacht, und um ehrlich zu sein, wusste ich nicht, wo ich es posten sollte. Ich ging mit dem Namen der Seiten, wobei ich dachte, dass SO allgemeiner ist, und SU ist mehr Admin-Kram. Ich finde am schnellsten Shell-Skripting ist Admin-bezogen. Sicher, Sie kommen aus dem einen oder anderen Grund in große tcl oder bash exklusive Projekte, in diesem Fall würde ich es auf Programmierung beschränken und nach SO veröffentlichen. Das war mehr ein Liner, und SU schien ein gutes Zuhause zu sein. Entschuldigung, wenn ich an der falschen Stelle gepostet habe, aber in einigen Fällen scheint es eine Grauzone zu sein. - user17245
@allentown: eigentlich Server Fault ist mehr Admin-Typ Zeug; Super User ist mehr Endanwender. (aber Power-User-Endnutzer.) Diese Frage ist wahrscheinlich auf jedem von SO / SF / SU willkommen. Sie haben bereits eine Antwort akzeptiert. Wenn Sie also zufrieden sind, können Sie es als erledigt bezeichnen. oder wenn Sie möchten, dass wir es nach SO / SF migrieren können; Markieren Sie es einfach für die Aufmerksamkeit des Moderators und sagen Sie uns, wo Sie es senden können. Vielen Dank! - quack quixote
@quack: Das ist in Ordnung, ich habe nur gedacht, dass dort eine bessere Antwort gefunden werden könnte, aber es scheint, dass es schon gefunden wurde. - Josh K


Antworten:


Ich weiß nicht, auf welchem ​​Betriebssystem Sie sind, aber auf FreeBSD 7.0+ hat Grep eine -o Option, um nur den Teil zurückzugeben, der dem Muster entspricht. Also könntest du
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

Liefert eine Liste von nur IP-Adressen aus dem 'filter_log' ...

Das funktioniert auf meinem System, aber ich weiß auch nicht, was deine Version von grep unterstützt.


7
2018-04-09 02:28



Ich denke, dass alle Antworten hier ausgezeichnete Möglichkeiten sind, das Endergebnis mit derselben Antwort zu lernen. Ich mag diesen hier besonders, da er leicht erinnerbar ist und nur mehrere Grep-Befehle per Pipe verkettet. Unter Mac OS X scheint ich die Option -o zu haben und natürlich die Option -E oft schon zu benutzen. Danke für Ihre Antwort - user17245


Sie können all dies in nur einem tun awk Befehl. Keine Notwendigkeit, andere Werkzeuge zu verwenden

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)

3
2018-04-09 02:44



Danke, das funktioniert, awk kann deinen Kopf manchmal etwas verletzen, aber ich gewöhne mich an den für FOO .... ein Liner-Aspekt von schnellen Sachen in der Shell. Sehr kraftvoll. - user17245


Sie können die Sekunde verkürzen grep ein bisschen so:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

Um die erste Frage zu beantworten, ermöglichen doppelte Anführungszeichen der Shell, verschiedene Dinge wie die variable Erweiterung auszuführen, aber einige Metazeichen davor zu schützen, dass sie maskiert werden müssen. Einfache Anführungszeichen verhindern, dass die Shell diese Erweiterungen ausführt. Wenn Sie keine Anführungszeichen verwenden, bleiben die Dinge weit offen.

$ 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"))

Sie können mehr im Abschnitt "QUOTING" von man bash


2
2018-04-09 04:16



Großartig schreiben, danke. Das muss ich auch mit dem IFS regulieren, da war ich neulich ziemlich fertig, habe es aber geschafft, IFS dazu zu bringen, nett zu spielen. Es ist eine schreckliche Sache, wenn Sie IFS gesetzt haben und es vergessen haben, wundern Sie sich, wtf geht seit einer Stunde weiter. - user17245
Es ist eine gute Idee, in der Gewohnheit zu sein, immer den Wert von zu sparen IFS und stelle es so schnell wie möglich wieder her: saveIFS="$IFS"; IFS=","; do_something; IFS="$saveIFS"; do_other_stuff - Dennis Williamson
+1 Guten Ruf auf die Regex, ich benutze es nicht viel, also bin ich ein wenig ineffizient. - Chris S


Schaut auf die xargs Befehl. Sie sollten etwas tun können wie:

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

Das mag es nicht genau sein, aber xargs ist der Befehl, den Sie verwenden möchten


1
2018-04-09 01:38