regex strings ignorieren

regex strings ignorieren

am 21.03.2006 13:54:34 von Volker Pohlers

Hallo,

ich möchte ein Suchen/Ersetzen durchführen. Texte zwischen zwei " "
sollen dabei aber nicht bearbeitet werden. Wie macht man das am besten?

Z.B. um im Quelltext Variablennamen zu ändern, aber eben nicht in
Zeichenketten. Dort sollen die originalen Texte erhalten bleiben, auch
wenn sie zufällig wie die Variable heißen.

mfg
Volker

Re: regex strings ignorieren

am 21.03.2006 15:20:14 von Volker Pohlers

Volker Pohlers schrieb:

Nachtrag:

Das ist meine jetzige Lösung. Ich finde sie aber nicht besonders effizient.

my @a = split /(")/, $line;
$line = '';
foreach $i (0..@a) {
if ($i%4==0) { $line .= expand ($a[$i]) }
else { $line .= $a[$i] }
}
$line;

mfg
Volker

Re: regex strings ignorieren

am 21.03.2006 17:48:20 von Ingo Menger

Volker Pohlers schrieb:

> Volker Pohlers schrieb:
>
> Nachtrag:
>
> Das ist meine jetzige Lösung. Ich finde sie aber nicht besonders effizi=
ent.
>
> my @a =3D split /(")/, $line;
> $line =3D '';
> foreach $i (0..@a) {
> if ($i%4==0) { $line .=3D expand ($a[$i]) }
> else { $line .=3D $a[$i] }
> }
> $line;

Wieso $i%4?
Was ist mit " innerhalb von Zeichenketten?

Ich würde folgenden Ansatz vorschlagen:

my $instr =3D 0;
my $vpat =3D ... pattern für zu ersetzende Variablennamen ...;
my $out =3D ""; # Ergebnis
while ($line =3D~ m/\G($vpat|"|\\"|.)/gc) {
my $have =3D $1;
if ($have eq '"') { $instr ^=3D 1; $out .=3D '"'; next; }
if ($have =3D~ m/$vpat/) { $out .=3D $instr ? expand($have) : $have;
next; }
out .=3D $have;
}

Erklärung: man matcht entweder einen Variablennamen oder ein " oder
ein \" oder ein einzelnes Zeichen und zwar immer nach dem letzten Match
(\G) bis man den String durchgescannt hat, d.h. Stringende oder \n nach
dem letzten Match kommt.
Dann schaut man sich jeweils an, was man gefunden hat: ist es ein ",
dann beginnt/endet ein String und man setzt das $instr-Flag
entsprechend. Dieses steuert, ob im Falle einer gefundenen Variablen
diese expandiert wird oder nicht.
\" und einzelne Zeichen werden einfach in die Ausgabe kopiert.

Anmerkung 1: Wenn z.B. die Variablennamen Schlüssel in einem Hash
sind, kann man das innere Match gegen die Variablennamen sicher auch
einsparen.
Anmerkung 2: Statt mit m/\G.../gc zu arbeiten, müßte auch ein
einfaches m// im array-Kontext funktionieren, wobei man das
Ergebnisarray dann durchlaufen kann, um das Ergebnis zusammenzusetzen.
Ich verwende allerdings m nie im Array-Kontext, mußt Du also selber
nachschauen.

Re: regex strings ignorieren

am 21.03.2006 19:37:49 von Frank Seitz

Volker Pohlers wrote:

> ich möchte ein Suchen/Ersetzen durchführen. Texte zwischen zwei " "
> sollen dabei aber nicht bearbeitet werden. Wie macht man das am besten?

Versuch's mal damit:

my @arr = $str =~ /"([^"]*)"/gs; # Text zw. "" extrahieren
$str =~ s/"[^"]*"/"%s"/gs; # %s stattdessen einsetzen

# Ersetzungen in $str durchführen

$str = sprintf $str,@arr; # Teile wieder zusammenfügen

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: regex strings ignorieren

am 22.03.2006 16:24:22 von Volker Pohlers

Frank Seitz schrieb:
> Volker Pohlers wrote:
>
>> ich möchte ein Suchen/Ersetzen durchführen. Texte zwischen zwei " "
>> sollen dabei aber nicht bearbeitet werden. Wie macht man das am besten?
>
> Versuch's mal damit:
>
> my @arr = $str =~ /"([^"]*)"/gs; # Text zw. "" extrahieren
> $str =~ s/"[^"]*"/"%s"/gs; # %s stattdessen einsetzen
>
> # Ersetzungen in $str durchführen
>
> $str = sprintf $str,@arr; # Teile wieder zusammenfügen
>
> Grüße
> Frank

Clever! Danke!!!

Gruß
Volker

Re: regex strings ignorieren

am 22.03.2006 16:27:47 von Volker Pohlers

Ingo Menger schrieb:
> Volker Pohlers schrieb:
>
>> my @a = split /(")/, $line;
>> $line = '';
>> foreach $i (0..@a) {
>> if ($i%4==0) { $line .= expand ($a[$i]) }
>> else { $line .= $a[$i] }
>> }
>> $line;
>
> Wieso $i%4?

weil mit split /(")/ auch die Gänsefüßchen ins Split-Array übernommen
werden. Also
Text-zu-ersetzen,Gänsefüßchen,Text-nicht-ersetzen,Gänsefüßch en,... Damit
ist nur der erste (also modulo 4) zu beackern.

> Was ist mit " innerhalb von Zeichenketten?
Die treten nicht auf. Und doppelte Gänsefüßchen werden durch obiges
Split korrekt behandelt.


> Ich würde folgenden Ansatz vorschlagen:
> ...
Die Lösung von Frank Seitz gefällt mir besser. Aber trotzdem vielen Dank!

Gruß
Volker

Re: regex strings ignorieren

am 22.03.2006 17:53:27 von Ingo Menger

Volker Pohlers schrieb:

> Ingo Menger schrieb:
> > Ich würde folgenden Ansatz vorschlagen:
> > ...
> Die Lösung von Frank Seitz gefällt mir besser. Aber trotzdem vielen D=
ank!

Kein Wunder, sie *ist* ja tatsächlich auch besser.