RegEx - Ausdruck 2 mal eretzen

Hallo - ich mal wieder! :smile:
Wie schon gesagt, will ich einen Ausdruck sozusagen 2 mal ersetzen:

$message =~ s/() ([^]*) ()/g;

Also das, was in der 2. Klammer steht soll noch mal ersetzt werden und zwar mit tr///. $2 ist ja read_only - man kann die Variable also nicht verändern.
Wie lässt sich das lösen?

Mal wieder Danke im Vorraus

Christoph

Hallo,

Hallo - ich mal wieder! :smile:
Wie schon gesagt, will ich einen Ausdruck sozusagen 2 mal
ersetzen:

> $message =~ s/() ([^]\*) ()/g;

Also das, was in der 2. Klammer steht soll noch mal ersetzt
werden und zwar mit tr///. $2 ist ja read_only - man kann die
Variable also nicht verändern.
Wie lässt sich das lösen?

Mit den /e-Modifier, der dafür sorgt, dass die rechte Seite des Regex-Operators wie ganz normaler Perl-Code ausgeführt wird. Also
$message =~ s/(…) (…) (…)/subst_funktion($1, $2, $3)/g;
sub subst_funktion {
my ($m1, $m2, $m3) = @_;
$m2 =~ tr/bar/foo/

wichtig: am Ende einen String zurückgeben:

return join(’|’, $m1, $m2, $m3);
}

HTH,
Moritz

Boah - wie geil is das denn.
Ich danke vielmals - genau das, was ich gesucht hab.
mfg Christoph

Hallo

Wie schon gesagt, will ich einen Ausdruck sozusagen 2 mal
ersetzen:

$message =~ s/() ([^]*) ()/g;

Also das, was in der 2. Klammer steht soll noch mal ersetzt
werden und zwar mit tr///. $2 ist ja read_only - man kann die
Variable also nicht verändern.
Wie lässt sich das lösen?

Moritz hat ja eine (imho zu komplizierte) Variante
angegeben, ich würde es aber möglicherweise einfacher
machen (ich bin nicht sicherm ob Moritz’ Variante
in /g bei Stringlängenveränderung überhaupt
funktioniert - kann aber durchaus sein):

 ...
 while( $message =~ /([^/g ) {
 my $p = pos $message;
 substr($message, $-[1], $+[1]-$-[1]) =~ tr/a-z/A-Z/;
 pos $message = $p
 }
 ...

Normalerweise „resetted“ eine Veränderung an $message
dessen pos(), also die skalare Position des
Matchoperators. Wenn wir einfach dieses pos()
aufheben und neu angeben, funktioniert es.

Der Ausdruck substr($message, $-[1], $+[1]-$-[1]) ist
genau der Bereich, der $1 entspricht. Hier werden
die Positionsfelder @- und @+ benutzt.

Grüße

CMБ

Moritz hat ja eine (imho zu komplizierte) Variante
angegeben,

ich finde seine lösung verständlich.

ich würde es aber möglicherweise einfacher
machen (ich bin nicht sicherm ob Moritz’ Variante
in /g bei Stringlängenveränderung überhaupt
funktioniert

tut sie - warum auch nicht? nicht jeder ersetzte string
muss die gleiche länge haben wie der originalstring.
und überhaupt - was ist an moritz’ lösung so schlecht?
magst du generell keine funktionen in ersetzungen aufrufen?

s/(wort)/length($1)/eg; # völlig legitim
  • kann aber durchaus sein):


while( $message =~ /([^/g )
{
my $p = pos $message;
substr($message, $-[1], $+[1]-$-[1]) =~ tr/a-z/A-Z/;
pos $message = $p
}

also ich weiss nicht, was *daran* jetzt einfacher sein soll =)

1 „Gefällt mir“

Mit den /e-Modifier, der dafür sorgt, dass die rechte Seite
des Regex-Operators wie ganz normaler Perl-Code ausgeführt
wird. Also

[…]
wobei du in deinem beispiel genau diesen e-modifier vergessen hast =)

Hallo Tina,

Moritz hat ja eine (imho zu komplizierte) Variante
angegeben,

ich finde seine lösung verständlich.

tut sie - warum auch nicht? nicht jeder ersetzte string
muss die gleiche länge haben wie der originalstring.
und überhaupt - was ist an moritz’ lösung so schlecht?
magst du generell keine funktionen in ersetzungen aufrufen?

Schon, ich mach das auch gerne gelegentlich - aber
Du hast recht - es war ja ein tr// gefordert und bei
diesem bleibt ja auch die Stringlänge identisch.

Irgendwas hatte meiner Ansicht nach nicht an Moritz’ Version
funktioniert (glaubte ich zu sehen) - aber nach eingängiger
Prüfung (durch Deinen Hinweis - danke) denke ich, das die
Version von Moritz doch u.U. die bessere Variante ist.
Meine Interpretation der Moritzschen variante:

 ...
 $message =~ s/()([^)/subst\_funktion($1,$2,$3)/eg; 
 
 sub subst\_funktion {
 (local $\_=[@\_])-\>[1] =~ tr/a-z/A-Z/;
 return "@$\_"
 }
 ...

Sorry für meine vorschnelle Äusserung. Ich werd das
händisch mit Sternchen abarbeiten :wink:

Grüße

CMБ

Schon, ich mach das auch gerne gelegentlich - aber
Du hast recht - es war ja ein tr// gefordert und bei
diesem bleibt ja auch die Stringlänge identisch.

also um genau zu sein bleibt bei einem tr/// die länge nicht immer identisch
(modifier /d und /s z.b.)
aber das muss sie auch gar nicht, es funktioniert so oder so.

Hallo Tina,

also um genau zu sein bleibt bei einem tr/// die länge nicht
immer identisch (modifier /d und /s z.b.)
aber das muss sie auch gar nicht, es funktioniert so oder so.

Richtig, wer weiss, was vorhin mit mir los
war …( zu viel anderen Kram gleichzeitig
um die Ohren). Irgendwie schwirrte mir die
Substitution „direkt im String-SV*“ im
Schädel rum, daher mein geäusserter Quark.

OK, zum Abschluss die getunte „Moritzsche Variante“ dafür :wink:

 ...
 sub xeeg { '($\_=$2)=~tr/a-z/A-Z/;"$1$\_$3"' }
 ...
 $message =~ s/() ([^)/xeeg/geex;
 ...

Aber trotzdem vermute ich, dass der OP
gerade ein XY-Problem löst … :wink:

Grüße

CMБ

Addendum

Das:


sub xeeg { ‚($_=$2)=~tr/a-z/A-Z/;"$1$_$3"‘ }

$message =~ s/() ([^)/xeeg/geex;

kläßt sich auch direkt

 ...
 $message =~ s{()([^)}{'(local$\_=$2)=~y/a-z/A-Z/;"$1$\_$3"'}gee;
 ...

ausdrücken.

Grüße

CMb