regex strings ignorieren

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
Volker Pohlers [ Di, 21 März 2006 13:54 ] [ ID #1239830 ]

Re: regex strings ignorieren

Volker Pohlers schrieb:

Nachtrag:

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

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

mfg
Volker
Volker Pohlers [ Di, 21 März 2006 15:20 ] [ ID #1239834 ]

Re: regex strings ignorieren

Volker Pohlers schrieb:

> Volker Pohlers schrieb:
>
> Nachtrag:
>
> Das ist meine jetzige Lösung. Ich finde sie aber nicht besonders effizi=
ent.
>
> my [at] a =3D split /(")/, $line;
> $line =3D '';
> foreach $i (0.. [at] a) {
> if ($i%4=3D=3D0) { $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.
Ingo Menger [ Di, 21 März 2006 17:48 ] [ ID #1239836 ]

Re: regex strings ignorieren

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 [at] arr = $str =~ /"([^"]*)"/gs; # Text zw. "" extrahieren
$str =~ s/"[^"]*"/"%s"/gs; # %s stattdessen einsetzen

# Ersetzungen in $str durchführen

$str = sprintf $str, [at] 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
Frank Seitz [ Di, 21 März 2006 19:37 ] [ ID #1239844 ]

Re: regex strings ignorieren

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 [at] arr = $str =~ /"([^"]*)"/gs; # Text zw. "" extrahieren
> $str =~ s/"[^"]*"/"%s"/gs; # %s stattdessen einsetzen
>
> # Ersetzungen in $str durchführen
>
> $str = sprintf $str, [at] arr; # Teile wieder zusammenfügen
>
> Grüße
> Frank

Clever! Danke!!!

Gruß
Volker
Volker Pohlers [ Mi, 22 März 2006 16:24 ] [ ID #1241683 ]

Re: regex strings ignorieren

Ingo Menger schrieb:
> Volker Pohlers schrieb:
>
>> my [at] a = split /(")/, $line;
>> $line = '';
>> foreach $i (0.. [at] 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
Volker Pohlers [ Mi, 22 März 2006 16:27 ] [ ID #1241684 ]

Re: regex strings ignorieren

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.
Ingo Menger [ Mi, 22 März 2006 17:53 ] [ ID #1241686 ]
Perl » de.comp.lang.perl.misc » regex strings ignorieren

Vorheriges Thema: Crontab aus Perl
Nächstes Thema: [C]ontroller fuer HTML::Mason-[V]iew