Perl regex

helionaut

Commander
Registriert
Jan. 2011
Beiträge
2.416
Hi,

Ich habe folgendes Datenformat:
abc;3 def;345 ghi;434 jklm;5667
abc;5 ghi;49
abc;6 def;385 ghi;4534

Als ausgabe möchte ich nur die zahlen nach abc; und ghi;
3 434
5 49
6 4534


Das beste was ich bis jetzt hinbekommen habe ist:
Code:
grep -oP '(?<=abc;|ghi;)\w+'

Aber das listet alles nacheinander auf, also
3
434
5
49
6
4534

Wie bekomme ich die beiden parameter nach abc; und ghi; auf einer zeile ausgegeben?
 
Also wenn ich das richtig sehe, fehlt da einfach eine Klammerung - mit dem '+' wiederholst du nur das \w, aber du willst glaube ich den gesamten Ausdruck vorher wiederholen.

Edit: Oder auch nicht. Hm, ich glaube, bei solchen Sachen ist man mit awk besser bedient als mit grep.

Nebenbei verstehe ich diesen Teil der Syntax nicht:
Code:
?<=
Was genau macht das?
 
Zuletzt bearbeitet:
VikingGe schrieb:
Also wenn ich das richtig sehe, fehlt da einfach eine Klammerung - mit dem '+' wiederholst du nur das \w, aber du willst glaube ich den gesamten Ausdruck vorher wiederholen.
Wo gehört denn die Klammerung hin? Sorry, bin da totaler Anfänger.

Nebenbei verstehe ich diesen Teil der Syntax nicht:
Code:
?<=
Was genau macht das?
Das entfernt den Namen der Variable also das "abc;"
 
Ich habe Blödsinn erzählt. Gemeint hatte ich folgendes:
Code:
grep "((?<=abc;|ghi;)\d+)+"

funktioniert aber ebenfalls nicht, weil offenbar nur ein Match pro Zeile erkannt wird.

Was aber funktioniert, ist folgende Lösung mit sed:
Code:
sed -r -e 's/(abc|ghi);([0-9]+)/\2/g' -e 's/[a-zA-Z0-9_]+;[0-9]+ *//g' datei

- Der erste Teil filtert die Zahlen zu den gewünschten Variablen heraus, macht also aus "abc;1234" einfach "1234"
- der zweite Teil schmeißt alle Name-Werte-Paare aus dem String heraus, die noch übrig bleiben, inklusive folgender Leerzeichen.
 
Ok, sed wäre eine kluge idee. So werden allerdings die restlichen (nicht-gesuchten parameter) auch ausgegeben.
Im Moment raucht mein kopf :rolleyes:
Vielleicht nach der Mittagspause ^^
Danke schonmal.
 
Zuletzt bearbeitet:
Übersichtlicher wäre es so (in "text hab ich den zu bearbeiteten Text mal reingeklatscht):
Code:
grep -oP "(?<=abc;|ghi;)\d+" text|sed 'N;s/\n/ /'

macht man nur ein
Code:
grep --color -P "(?<=abc;|ghi;)\d+" text
dann sieht man, dass grep durchaus die Teile berücksichtigt, die man möchte:
abc;3 def;345 ghi;434 jklm;5667
abc;5 ghi;49
abc;6 def;385 ghi;4534

mit dem Flag -o (only) wird eben nur passendes, aber nicht die ganze Zeile angezeigt; grep macht aber für jeden Match eine neue Zeile
mit
Code:
sed 'N;s/\n/ /'
packen wir jeweils 2 Zeilen zusammen, genauer:
mit
Code:
sed 'N'
packen wir die nachfolgende Zeile mit den Pattern Space

mit
Code:
sed 's/\n/ /'
wenden wir diese replace Aktion auf den Pattern Space an (der ja jetzt 2 Zeilen inkl. diesem Umbruch enthält und ersetzen diesem mit einem Leerzeichen

übrig bleibt
3 434
5 49
6 4534


zu (?<=...)
das "entfernt" nichts, sondern berücksichtigt zwar diesen Ausdruck, behandelt ihn aber nicht als einen Teil des gefundenen Ausdrucks, ähnlich wie bei Look Arounds
nennt sich "non-capturing group"
 
eremit007 schrieb:
Wie bekomme ich die beiden parameter nach abc; und ghi; auf einer zeile ausgegeben?

Meines Erachtens geht das mit grep gar nicht.

Ausschnitt aus "man grep":
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

Meine Lösung:
Code:
perl -ne  '/abc;(\d+).*?ghi;(\d+)/; print $1, " ", $2, "\n";' deinfile.txt

liefert Dein gewünschtes
Code:
3 434
5 49
6 4534


HTH

BigNum
 
Fantastisch, danke :)
Hab's mit BigNum's Perl-Zeile gemacht
 
Zurück
Oben