Siechfred: inhalt zwischen 2 Wörtern auslesen (regex)

Beitrag lesen

Hm, ja :) Ich sehe jetzt, dass $1 jetzt den Inhalt des ersten Klammerpaares ist, aber das ist auch das, was ich erwartete. Nur die Funktionsweise des Lookaheads will mir nicht so recht ins Head ;)

Grundwissen zum Verständnis: Die Klammer um Lookaround-Konstrukte dient *nicht* der Gruppierung in Teilausdrücke. Mein Beispiel mal etwas abgewandelt:

my $text = 'foo:bar:baz:bum:foo';  
$text =~ /(?<=foo:)(.*)(?=:foo)/;

Jetzt scheint dein erster Denkfehler zu sein, dass $1 das Lookbehind, $3 das Lookahead und $2 alles dazwischen enthält, doch dem ist nicht so. Es gibt nur einen geklammerten Teilausdruck, und das ist in $1 alles zwischen 'foo'. Die Lookarounds dagegen sind 'zero-width assertions'.

bedeutet, dass das Lookahead-Konstrukt nicht Bestandteil des zu suchenden und ersetzenden Stringteils ist.
... und wurde deswegen bei meinem Beispiel mit ausgegeben? Wozu ist dann so etwas gut, wollte der OP nicht $1 extrahieren?

Das bekommt er auch, indem er $1 abfragt. Um mal mein Beispiel auseinanderzunehmen:

(?<=foo:)(.*)(?=:foo) = Finde alles, was zwischen 'foo:' und ':foo' steht. Ergebnis: 'bar:baz:bum'. Das sollte dir einleuchten :)

Jetzt zurück zu deiner Ersetzung:

$text = s/(?<=foo:)(.*)(?=:foo)/$1/s;

Der String lautete 'foo:bar:baz:bum:foo', was der RegExp bedeutet, habe ich geschrieben. Im Ergebnis passt also vom Ausgangsstring der Teilstring 'bar:baz:bum' auf den RegExp. Dieser Teil wird zugleich in $1 geklammert. Wenn du dir jetzt dein Beispiel ansiehst, wirst du sehen, dass deine Ersetzung keine echte[tm] ist, denn der Teilstring, der auf das Muster passt, ist identisch mit dem Teilstring, den du in $1 gespeichert hast. Ergo wird oben stehende Anweisung im Ergebnis nichts am Ausgangsstring verändern, da 'bar:baz:bum' durch 'bar:baz:bum' ersetzt wird. Suchen- und Ersetzen ist eben nicht zum Extrahieren von Teilstrings geeignet, deinen Ansatz würde ich durch

$text =~ s/(foo:|:foo)//gs;

lösen.

Weil //m bedeutet, dass die Zeichenklasse '.' auf alles *außer* Newlines matcht, während //s die Newlines einschließt.
Erlaubt nicht »m« das Suchen über mehrere Zeilen hinweg, in dem es den zu durchsuchenden Text betrachtet, als wäre es -sozusagen- eine Zeile?

Nein, das tut jeder RegExp, so lange die mehreren Zeilen in einem Skalar durch Newlines getrennt vorliegen. Die besondere Bedeutung liegt neben der Zeichenklasse '.' im Verhalten der Anker '^' und '$'. Bei //s sind dies Stringanfang und -ende, bei //m sind dies Zeilenanfang- und Ende. Beispiele mit Erläuterung dazu findest du in perlretut (musst ein bisschen nach unten scrollen).

Siechfred

--
Ein Selbständiger ist jemand, der bereit ist, 16 Stunden am Tag zu arbeiten, nur um nicht 8 Stunden für einen Anderen arbeiten zu müssen.