Submatches von s/// verarbeiten

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
Frank Seitz [ Mi, 15 November 2006 23:32 ] [ ID #1537299 ]

Re: Submatches von s/// verarbeiten

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])"

--
Alexander Bartolich [ Do, 16 November 2006 00:33 ] [ ID #1537301 ]

Re: Submatches von s/// verarbeiten

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 [at] mat = $str =~ /$reg/)
{
$str =~ s/$reg//;
# [at] 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
Frank Seitz [ Do, 16 November 2006 00:53 ] [ ID #1537302 ]

Re: Submatches von s/// verarbeiten

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 [at] mat = $str =~ /$reg/)
> {
> $str =~ s/$reg//;
> # [at] mat verarbeiten
> }
>
> Vielleicht hat ja jemand noch eine bessere Idee.

Besser? Keine Ahnung. Anders? Ja.

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

-Christian
Christian Winter [ Do, 16 November 2006 09:04 ] [ ID #1538590 ]

Re: Submatches von s/// verarbeiten

Christian Winter!

> Besser? Keine Ahnung. Anders? Ja.
>
> if( $str =~ s/$reg// )
> {
> [at] 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
Daniel Fischer [ Do, 16 November 2006 09:21 ] [ ID #1538592 ]

Re: Submatches von s/// verarbeiten

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

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

Für gewisse Werte von »besser«.


Frank
Frank Wiegand [ Do, 16 November 2006 09:55 ] [ ID #1538593 ]

Re: Submatches von s/// verarbeiten

Daniel Fischer schrieb:
> Christian Winter!
>> Besser? Keine Ahnung. Anders? Ja.
>>
>> if( $str =~ s/$reg// )
>> {
>> [at] 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 [at] mat = map { $$_ } 1 .. $#+ if( $str =~ s/$reg// );

-Christian
Christian Winter [ Do, 16 November 2006 10:00 ] [ ID #1538594 ]

Re: Submatches von s/// verarbeiten

Christian Winter wrote:

> Aber der Einzeiler hätte schon was golfiges.
>
> my [at] 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
Frank Seitz [ Do, 16 November 2006 10:10 ] [ ID #1538595 ]

Re: Submatches von s/// verarbeiten

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
Mirco Wahab [ Do, 16 November 2006 11:14 ] [ ID #1538597 ]

Re: Submatches von s/// verarbeiten

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 [at] mat = map { $$_ } 1 .. $#+;
print " [at] 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
Frank Seitz [ Do, 16 November 2006 13:32 ] [ ID #1538599 ]

Re: Submatches von s/// verarbeiten

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 [at] mat, map +(substr($str,$-[$_],$+[$_]-$-[$_]) ), 1..-1+ [at] + })';

my $reg = qr/(\w+)=(\w+)/x;
my [at] mat = ();

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


also einen "Akkumulator" verwenden.

Viele Grüße

Mirco
Mirco Wahab [ Do, 16 November 2006 14:02 ] [ ID #1538601 ]

Re: Submatches von s/// verarbeiten

Frank Seitz <devnull4711 [at] web.de> 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?
Olaf Schneider [ Fr, 17 November 2006 00:22 ] [ ID #1538606 ]

Re: Submatches von s/// verarbeiten

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
Christian Winter [ Fr, 17 November 2006 09:28 ] [ ID #1539915 ]

Re: Submatches von s/// verarbeiten

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
Frank Seitz [ Fr, 17 November 2006 10:10 ] [ ID #1539918 ]

Re: Submatches von s/// verarbeiten

Frank Seitz <devnull4711 [at] web.de> 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.
Olaf Schneider [ Fr, 17 November 2006 18:58 ] [ ID #1539925 ]

Re: Submatches von s/// verarbeiten

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
Frank Seitz [ Fr, 17 November 2006 19:32 ] [ ID #1539927 ]

Re: Submatches von s/// verarbeiten

Frank Seitz <devnull4711 [at] web.de> 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).
Olaf Schneider [ Fr, 17 November 2006 23:31 ] [ ID #1539929 ]

Re: Submatches von s/// verarbeiten

Olaf Schneider wrote:
> Frank Seitz <devnull4711 [at] web.de> 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
Frank Seitz [ Sa, 18 November 2006 09:16 ] [ ID #1540569 ]
Perl » de.comp.lang.perl.misc » Submatches von s/// verarbeiten

Vorheriges Thema: freier Webshop in Perl?
Nächstes Thema: Programm beenden wenn n Sekunden keine STDIN