Submatches von s/// verarbeiten

Submatches von s/// verarbeiten

am 15.11.2006 23:32:28 von Frank Seitz

Hallo,

ich habe eine Substitution mit einem Regex $reg:

$str =~ s/$reg//;

$reg enthält eine unbekannte Anzahl an Submatches
(...), die ich im Anschluss verarbeiten möchte.
Wie mache ich das am besten? Die Variablen $1, $2 usw.
nützen mir dabei wohl nicht nicht viel.
Hat jemand eine Idee?

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: Submatches von s/// verarbeiten

am 16.11.2006 00:33:48 von Alexander Bartolich

Frank Seitz schrieb:
> [...]
> $reg enthält eine unbekannte Anzahl an Submatches
> (...), die ich im Anschluss verarbeiten möchte.
> Wie mache ich das am besten? Die Variablen $1, $2 usw.
> nützen mir dabei wohl nicht nicht viel.

man perlvar
# [...]
# You can use $#+ to determine how many subgroups were in the
# last successful match.
# [...]
# $1 is the same as "substr($var, $-[1], $+[1] - $-[1])"
# $2 is the same as "substr($var, $-[2], $+[2] - $-[2])"
# $3 is the same as "substr($var, $-[3], $+[3] - $-[3])"

--

Re: Submatches von s/// verarbeiten

am 16.11.2006 00:53:33 von Frank Seitz

Alexander Bartolich wrote:
> Frank Seitz schrieb:
>>[...]
>>$reg enthält eine unbekannte Anzahl an Submatches
>>(...), die ich im Anschluss verarbeiten möchte.
>>Wie mache ich das am besten? Die Variablen $1, $2 usw.
>>nützen mir dabei wohl nicht nicht viel.
>
> man perlvar
> # [...]
> # You can use $#+ to determine how many subgroups were in the
> # last successful match.
> # [...]
> # $1 is the same as "substr($var, $-[1], $+[1] - $-[1])"
> # $2 is the same as "substr($var, $-[2], $+[2] - $-[2])"
> # $3 is the same as "substr($var, $-[3], $+[3] - $-[3])"

Das geht so direkt nicht. Da $var durch die Substitution
verändert wird, sind die Indizes nicht mehr gültig.
Ich könnte den Wert von $var natürlich kopieren.
Irgendwie macht mich der Vorschlag nicht glücklich.

Mir ist zwischenzeitlich dies hier eingefallen,
das ist zumindest halbwegs kurz:

if (my @mat = $str =~ /$reg/)
{
$str =~ s/$reg//;
# @mat verarbeiten
}

Vielleicht hat ja jemand noch eine bessere Idee.

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: Submatches von s/// verarbeiten

am 16.11.2006 09:04:20 von Christian Winter

Frank Seitz schrieb:
> Alexander Bartolich wrote:
>> Frank Seitz schrieb:
>>> [...]
>>> $reg enthält eine unbekannte Anzahl an Submatches
>>> (...), die ich im Anschluss verarbeiten möchte.
>>> Wie mache ich das am besten? Die Variablen $1, $2 usw.
>>> nützen mir dabei wohl nicht nicht viel.
>> man perlvar
>> # [...]
>> # You can use $#+ to determine how many subgroups were in the
>> # last successful match.
>> # [...]
>> # $1 is the same as "substr($var, $-[1], $+[1] - $-[1])"
>> # $2 is the same as "substr($var, $-[2], $+[2] - $-[2])"
>> # $3 is the same as "substr($var, $-[3], $+[3] - $-[3])"
>
> Das geht so direkt nicht. Da $var durch die Substitution
> verändert wird, sind die Indizes nicht mehr gültig.
> Ich könnte den Wert von $var natürlich kopieren.
> Irgendwie macht mich der Vorschlag nicht glücklich.
>
> Mir ist zwischenzeitlich dies hier eingefallen,
> das ist zumindest halbwegs kurz:
>
> if (my @mat = $str =~ /$reg/)
> {
> $str =~ s/$reg//;
> # @mat verarbeiten
> }
>
> Vielleicht hat ja jemand noch eine bessere Idee.

Besser? Keine Ahnung. Anders? Ja.

if( $str =~ s/$reg// )
{
@mat = map { $$_ } 0 .. $#+;
}

-Christian

Re: Submatches von s/// verarbeiten

am 16.11.2006 09:21:08 von Daniel Fischer

Christian Winter!

> Besser? Keine Ahnung. Anders? Ja.
>
> if( $str =~ s/$reg// )
> {
> @mat = map { $$_ } 0 .. $#+;
> }

Das ist speziell dann nicht besser, wenn $0 der Pfad des Scripts ist. ;-)

Und man kann es noch in ein Statement schreiben, aber dann ist es
definitiv nicht mehr besser ;-)


Gruß
Daniel

Re: Submatches von s/// verarbeiten

am 16.11.2006 09:55:35 von Frank Wiegand

Frank Seitz schrieb:
> if (my @mat = $str =~ /$reg/)
> {
> $str =~ s/$reg//;
> # @mat verarbeiten
> }
>
> Vielleicht hat ja jemand noch eine bessere Idee.

{
no strict 'refs';
$str =~ s/$reg/@mat=grep defined,map$$_,1..32;''/e;
}

Für gewisse Werte von »besser«.


Frank

Re: Submatches von s/// verarbeiten

am 16.11.2006 10:00:25 von Christian Winter

Daniel Fischer schrieb:
> Christian Winter!
>> Besser? Keine Ahnung. Anders? Ja.
>>
>> if( $str =~ s/$reg// )
>> {
>> @mat = map { $$_ } 0 .. $#+;
>> }
>
> Das ist speziell dann nicht besser, wenn $0 der Pfad des Scripts ist. ;-)
>
> Und man kann es noch in ein Statement schreiben, aber dann ist es
> definitiv nicht mehr besser ;-)

Arghl. Ich geb's ja zu, aus der Hüfte nach hinten geschossen
und mitten durch die Brust ins Knie getroffen.
Aber der Einzeiler hätte schon was golfiges.

my @mat = map { $$_ } 1 .. $#+ if( $str =~ s/$reg// );

-Christian

Re: Submatches von s/// verarbeiten

am 16.11.2006 10:10:27 von Frank Seitz

Christian Winter wrote:

> Aber der Einzeiler hätte schon was golfiges.
>
> my @mat = map { $$_ } 1 .. $#+ if( $str =~ s/$reg// );

Die runden Klammern kannst Du noch weglassen.
Allerdings fehlt das "no strict 'refs'", das in
einer ordentlichen Umgebung wegen der Symbolic Reference
erforderlich ist.

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: Submatches von s/// verarbeiten

am 16.11.2006 11:14:58 von Mirco Wahab

Frank Seitz schrieb:
> ich habe eine Substitution mit einem Regex $reg:
>
> $str =~ s/$reg//;
>
> $reg enthält eine unbekannte Anzahl an Submatches
> (...), die ich im Anschluss verarbeiten möchte.
> Wie mache ich das am besten? Die Variablen $1, $2 usw.
> nützen mir dabei wohl nicht nicht viel.
> Hat jemand eine Idee?

Hallo Frank,

kannst du mal ein konkretes kleines
"Workflow"-Beispiel dazu, vielleicht mit
einer Regex und ein paar Daten angeben?

Deine Beschreibungen sind mir zu abstrakt ;-)


Viele Grüße

M. Wahab

Re: Submatches von s/// verarbeiten

am 16.11.2006 13:32:16 von Frank Seitz

Mirco Wahab wrote:
> Frank Seitz schrieb:
>
>>ich habe eine Substitution mit einem Regex $reg:
>>
>> $str =~ s/$reg//;
>>
>>$reg enthält eine unbekannte Anzahl an Submatches
>>(...), die ich im Anschluss verarbeiten möchte.
>>Wie mache ich das am besten? Die Variablen $1, $2 usw.
>>nützen mir dabei wohl nicht nicht viel.
>>Hat jemand eine Idee?
>
> Hallo Frank,
>
> kannst du mal ein konkretes kleines
> "Workflow"-Beispiel dazu, vielleicht mit
> einer Regex und ein paar Daten angeben?
>
> Deine Beschreibungen sind mir zu abstrakt ;-)

Es sollte Dir zu denken geben, dass andere diese
Verständnisschwierigkeiten haben :)

Mein konkreter Anwendungsfall ist zu kompliziert, um
ihn hier zu erklären. Das folgende Beispiel ist
aus den Fingern gesogen:

#---------------------------------------------
#!/usr/local/bin/perl -w

use strict;

# Beispielstring, Beispielregex (mit 2 Submatches)

my $str = 'a b c=d e';
my $reg = qr/(\w+)=(\w+)/;

# Liefere die Werte der Submatches, ohne
# die Anzahl vorab zu kennen

if ($str =~ s/$reg//)
{
no strict 'refs';
my @mat = map { $$_ } 1 .. $#+;
print "@mat\n";
}
__END__
c d
#---------------------------------------------

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: Submatches von s/// verarbeiten

am 16.11.2006 14:02:52 von Mirco Wahab

Frank Seitz schrieb:
> Mirco Wahab wrote:
>> Frank Seitz schrieb:
>>> ich habe eine Substitution mit einem Regex $reg:
>>> $str =~ s/$reg//;
>> Deine Beschreibungen sind mir zu abstrakt ;-)
> Es sollte Dir zu denken geben, dass andere diese
> Verständnisschwierigkeiten haben :)
> ... ... Das folgende Beispiel ist
> aus den Fingern gesogen:
>

OK, ich bin schon mal auch schwer von Begriff.
Dein Szenario lies imho noch zu vieles offen ...

Vielleicht würde ich das so machen:

use strict;
use warnings;
use re 'eval';

my $str = 'a b c=d e'; # Beispielstring, Beispielregex (mit 2 Submatches)
my $acc = '(?{push @mat, map +(substr($str,$-[$_],$+[$_]-$-[$_]) ), 1..-1+@+ })';

my $reg = qr/(\w+)=(\w+)/x;
my @mat = ();

$str =~ s/$reg$acc//g;
print scalar @mat, "\n@mat\n";


also einen "Akkumulator" verwenden.

Viele Grüße

Mirco

Re: Submatches von s/// verarbeiten

am 17.11.2006 00:22:50 von Olaf Schneider

Frank Seitz wrote:

> ich habe eine Substitution mit einem Regex $reg:

> $str =~ s/$reg//;

> $reg enthält eine unbekannte Anzahl an Submatches
> (...), die ich im Anschluss verarbeiten möchte.
> Wie mache ich das am besten? Die Variablen $1, $2 usw.
> nützen mir dabei wohl nicht nicht viel.
> Hat jemand eine Idee?

$str="ab11bcde12n42nn";
while($str =~s/(\d\d)//) {
print "$1\n"
}
print "$str\n";'

liefert:

11
12
42
abbcdennn

Kennt jemand die Stelle in der Doku, wo dieses Verhalten
erklärt bzw. beschrieben ist?

Re: Submatches von s/// verarbeiten

am 17.11.2006 09:28:23 von Christian Winter

Olaf Schneider schrieb:
> $str="ab11bcde12n42nn";
> while($str =~s/(\d\d)//) {
> print "$1\n"
> }
> print "$str\n";'
>
> liefert:
>
> 11
> 12
> 42
> abbcdennn
>
> Kennt jemand die Stelle in der Doku, wo dieses Verhalten
> erklärt bzw. beschrieben ist?

Welches "Verhalten" meinst Du?

-Christian

Re: Submatches von s/// verarbeiten

am 17.11.2006 10:10:33 von Frank Seitz

Christian Winter wrote:
> Olaf Schneider schrieb:
>>
>>$str="ab11bcde12n42nn";
>>while($str =~s/(\d\d)//) {
>> print "$1\n"
>>}
>>print "$str\n";'
>>
>>liefert:
>>
>>11
>>12
>>42
>>abbcdennn
>>
>>Kennt jemand die Stelle in der Doku, wo dieses Verhalten
>>erklärt bzw. beschrieben ist?
>
> Welches "Verhalten" meinst Du?

Ja, was überrascht Dich an dem Ergebnis?
Beachte, dass s/// nicht nur matcht, sondern das Gematchte
substituiert, und zwar in dem Fall durch nichts (Leerstring).

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: Submatches von s/// verarbeiten

am 17.11.2006 18:58:04 von Olaf Schneider

Frank Seitz wrote:

> Christian Winter wrote:

>> Olaf Schneider schrieb:

>>>while($str =~s/(\d\d)//) {

>>>Kennt jemand die Stelle in der Doku, wo dieses Verhalten
>>>erklärt bzw. beschrieben ist?
>>
>> Welches "Verhalten" meinst Du?

Ok, beim genaueren Nachdenken ist es nicht mehr überraschend.
Mir erschien diese Floskel gestern abend aber so elegant, daß
ich irgendeine Magie dahinter vermutet habe. [1]

> Ja, was überrascht Dich an dem Ergebnis?

Mich wundert jetzt nur, daß Du als Poster von:

| ich habe eine Substitution mit einem Regex $reg:
|
| $str =~ s/$reg//;
|
| $reg enthält eine unbekannte Anzahl an Submatches
| (...), die ich im Anschluss verarbeiten möchte.
| Wie mache ich das am besten? Die Variablen $1, $2 usw.
| nützen mir dabei wohl nicht nicht viel.
| Hat jemand eine Idee?

nicht überrascht bist. Schließlich wollest Du doch genau
sowas.

[1] Und auch ohne Magie wäre es schön, so ein Beispiel
in der Doku zu finden.

Re: Submatches von s/// verarbeiten

am 17.11.2006 19:32:04 von Frank Seitz

Olaf Schneider wrote:

> Mich wundert jetzt nur, daß Du als Poster von:
>
> | ich habe eine Substitution mit einem Regex $reg:
> |
> | $str =~ s/$reg//;
> |
> | $reg enthält eine unbekannte Anzahl an Submatches
> | (...), die ich im Anschluss verarbeiten möchte.
> | Wie mache ich das am besten? Die Variablen $1, $2 usw.
> | nützen mir dabei wohl nicht nicht viel.
> | Hat jemand eine Idee?
>
> nicht überrascht bist. Schließlich wollest Du doch genau
> sowas.

Nein, bei meiner Frage ging es um etwas anderes:
Ich habe Substitutions-Regexes mit nicht nur einem,
sondern mit mehreren Subausdrücken (...) und möchte die Werte
aller Submatches haben. Das ist etwas anderes als
eine Substitution mehrfach anzuwenden.

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: Submatches von s/// verarbeiten

am 17.11.2006 23:31:19 von Olaf Schneider

Frank Seitz wrote:

> Ich habe Substitutions-Regexes mit nicht nur einem,
> sondern mit mehreren Subausdrücken (...) und möchte die Werte
> aller Submatches haben. Das ist etwas anderes als
> eine Substitution mehrfach anzuwenden.

Meinst Du mit "Submatches" das was in der Doku zu m// als
"subexpressions matched by the parentheses" umschrieben ist?

Für sowas ist doch die Einbettung von Code in den Regex gedacht:

$str="foo a1 b17 x509 bar";
$str=~s/(?:\s*\b([a-z]\d+)\b\s*(?{print "$^N\n"}))+//;
print "$str\n";'

ergibt:

a1
b17
x509
foobar

Zugegebenermaßen sind die (?{}) assertions experimentell
(zumindest in meinem Perl 5.8.0 hier).

Re: Submatches von s/// verarbeiten

am 18.11.2006 09:16:37 von Frank Seitz

Olaf Schneider wrote:
> Frank Seitz wrote:
>>
>>Ich habe Substitutions-Regexes mit nicht nur einem,
>>sondern mit mehreren Subausdrücken (...) und möchte die Werte
>>aller Submatches haben. Das ist etwas anderes als
>>eine Substitution mehrfach anzuwenden.
>
> Meinst Du mit "Submatches" das was in der Doku zu m// als
> "subexpressions matched by the parentheses" umschrieben ist?

Vermutlich ja (ich habe das jetzt nicht nachgelesen).

> Für sowas ist doch die Einbettung von Code in den Regex gedacht:
>
> $str="foo a1 b17 x509 bar";
> $str=~s/(?:\s*\b([a-z]\d+)\b\s*(?{print "$^N\n"}))+//;
> print "$str\n";'
>
> ergibt:
>
> a1
> b17
> x509
> foobar
>
> Zugegebenermaßen sind die (?{}) assertions experimentell
> (zumindest in meinem Perl 5.8.0 hier).

Den Weg hat Mirco Wahab auch schon vorgeschlagen.
Der ist mir aber zu umständlich.

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