grep mit Grenzen

kokiman

Lt. Commander
Registriert
Juni 2010
Beiträge
1.796
Hey, ich habe folgendes Problem zu dem ich irgendwie nichts finde.

Ich habe ein rießiges logfile aus dem ich strings rausfiltern soll. Gibt es da mit grep z.b linke und rechte Begrenzer festzulegen?

Der inhalt des Logs sieht so circa aus NR DATUM USER "GET /url/url2/url3/url4/ HTTP/1.1" und im Grunde genommen will ich nur die url ab url2 haben ohne dem HTTP am ende.
 
Wie Markus schon erwähnt hat wäre da "cut" ganz gut, welches du ja noch mit "grep" und/oder "sort" kombinieren kannst.

Vielleicht kannst Du ja mal eine Zeile aus deinem Log hier rein kopieren um dann dir einen konkreten vorschlag zu geben.
 
Code:
grep -Po "GET \/url\/.*? HTTP" logfile.log |sed -r 's/GET \/url\/(.*?) HTTP/\1/g'
grep Schalter
  • P - Suchmuster ist ein regulärer Ausdruck
  • o - nur die Zeichenfolge, welche auf den Ausdruck passt, wird angezeigt (anstatt der kompletten Zeile)

sed Schalter
  • r - Suchmuster ist ein regulärer Ausdruck

  • es wird nach "GET /url/<alles was hier steht> HTTP" gegrept
  • anschließend wird mit sed das "GET /url/" und das " HTTP" am Ende weg-ersetzt (bzw. es wird mit einem regulären Ausdruck nach "GET /url/<alles was hier steht> HTTP" gesucht und der komplette String mit "<alles was hier steht>" ersetzt)
 
Zuletzt bearbeitet:
Browny! schrieb:
Wie Markus schon erwähnt hat wäre da "cut" ganz gut, welches du ja noch mit "grep" und/oder "sort" kombinieren kannst.

Vielleicht kannst Du ja mal eine Zeile aus deinem Log hier rein kopieren um dann dir einen konkreten vorschlag zu geben.

Sorry, dass ich jetzt erst antworte.


Code:
xxx.xxx.xx.xxx - - [01/Dec/2010:14:02:30 +0100] "GET /test/test2/test3/test+test+test+test HTTP/1.1" 444 11111
So sähe es jetzt genau aus. Ich hab mir das cut nochmal genauer angeschaut, er schneidet sozusagen alles was hinter der angegeben Stelle (im ersten Falle " ") weg, richtig? Beim Beispiel von markus hat er mir dann nur "GET gezeigt. Ich will die ganzen daten dann auch in einer neuen Logdatei haben. So wurde mir wohl erstmal nur angezeigt was weggeschnitten wurde.
 
Zuletzt bearbeitet:
Ich wäre ja für:
Code:
grep -Po "(?<=GET ).*(?= HTTP)" <datei>
Durch die Lookarounds muss man nicht anschließend noch was wegschneiden.

Edit: Hab grad gesehen, dass du erst ab url2 matchen willst. Da url sicherlich eine variable Länge hat, man aber für lookarounds fixe Längen benötigt, muss man sich mit einem kleinen Trick helfen. mit \K kann man den bereits gematchten String zurücksetzen. Das Ergebnis sieht dann folgendermaßen aus:
Code:
grep -Po "GET /.*?/\K.*(?= HTTP)" <datei>
 
Zuletzt bearbeitet:
Freezedevil schrieb:
Ich wäre ja für:
Code:
grep -Po "(?<=GET ).*(?= HTTP)" <datei>
Durch die Lookarounds muss man nicht anschließend noch was wegschneiden.

Wenn ich das so schreibe und auch bei dem anderen grep Beispiel sagt er mir grep: invalid option -- P . Ich hatte auch vergessen zu sagen, dass ich nicht direkt auf Linux arbeite sondern mit UnxUtils auf einem Win Server arbeite.( falls das irgendwas ändert)
 
Offenbar ändert das was ;)

Dann musst du mal schauen was für Parameter du mitgeben musst um:
- Den Suchstring als regex zu interpretieren
- nur den gematchten Text zurückzugeben

Hoffentlich werden die Ausdrücke wenigstens gleich behandelt.
(Beachte auch meinen Edit oben)
 
Freezedevil schrieb:
Offenbar ändert das was ;)

Dann musst du mal schauen was für Parameter du mitgeben musst um:
- Den Suchstring als regex zu interpretieren
- nur den gematchten Text zurückzugeben

Hoffentlich werden die Ausdrücke wenigstens gleich behandelt.
(Beachte auch meinen Edit oben)

Hmpf. grep.jpg
 
Das sieht natürlich nicht so schön aus. Zumindest falls das alles ist.
Wie sieht es mit awk aus? (wenn ich richtig gegoogelt hab ist bei dir gawk dabei welches sich in diesem Fall hoffentlich genauso verhält)

Code:
awk '/GET .*? HTTP/ { url=$7; sub(/\/[^\/]*/, "", url); print url}' <datei>
bzw
gawk '/GET .*? HTTP/ { url=$7; sub(/\/[^\/]*/, "", url); print url}' <datei>
(ungetestet)
 
So macht er mir halt nur ein leeres Logfile


Code:
 grep -E "(?<=GET ).*(?= HTTP)" <datei> >> logfile.log

Und das awk Zeug versteh ich nicht so wirklich.
 
Das matcht so einfach nicht, da die Lookarounds damit glaube ich nicht unterstützt werden. Haste das awk mal probiert?

Edit: awk ist ne Scriptsprache und der entsprechende Befehl praktisch der Interpreter. Das ganze läuft zeilenbasiert ab.
Für jede Zeile die auf den regex am Anfang passt wird der darauf folgende Programmcode ausgeführt
regex: /GET .*? HTTP/
Programm: url=$7; sub(/\/[^\/]*/, "", url); print url

Eine Zeile wird immer in Variablen $1 bis $x aufgeteilt. Getrennt wird immer bei einem Leerzeichen. Daher ist in diesem Fall $7=/test/test2/test3/test+test+test+test.
Dieser Wert wird in die Variable url gespeichert.
Anschließend wird mit der Funktion sub(regex, replacement, target) der Anfang (in diesem Fall /test) durch nichts ersetzt, also weggeschnitten.
Zu guter letzt wird url ausgegeben.

Funktioniert bei mir soweit wie es soll.
 
Zuletzt bearbeitet:
Freezedevil schrieb:
Das matcht so einfach nicht, da die Lookarounds damit glaube ich nicht unterstützt werden.
und zu blöd für single quotes ist es auch noch :D (das liegt aber glaube an der shell)


Code:
grep -Po "GET \/url\/.*? HTTP" logfile.log |sed -r "s/GET \/url\/(.*?) HTTP/\1/g"
funzt bei mir mit diesen unixutils :)
 
Komisch. Warum sagt die Shell beim TE dann, dass er den Parameter P nicht kennt?
Im Zweifelsfall sollte dieses Bsp aber definitiv auch mit -E statt -P laufen.
 
Freezedevil schrieb:
Komisch. Warum sagt die Shell beim TE dann, dass er den Parameter P nicht kennt?
Im Zweifelsfall sollte dieses Bsp aber definitiv auch mit -E statt -P laufen.


muss dann daran liegen, dass ich mir die Utils frisch gezogen habe o_O
uutils_grep.png
 
Zuletzt bearbeitet:
Freezedevil schrieb:
Ok, damit müsste ja dann auch meine hübsche kurze Lösung gehen.

hat ich auch gehofft, aber entweder klappt was mit dem escapen / ausquoten nicht oder die perl regex sind nur halbherzig implementiert
 
Zurück
Oben