Thread Problem im Zusammenhang mit REs: kniffelig (9 answers)
Opened by Crian at 2005-08-25 13:20

Crian
 2005-08-25 13:20
#57368 #57368
User since
2003-08-04
5870 Artikel
ModeratorIn
[Homepage]
user image
Hallo,

ich habe ein vielleicht merkwürdig anmutendes Problem im Zusammenhang mit regulären Ausdrücken.
Ich hab auch schon eine Lösung für mein Problem, möchte aber hören, ob es schlaueres gibt.

Zu meinem Problem:
Ich habe in einem Text mehrere gleiche Teile (hier: <<A>>), von denen einige durch Klammern im regulären Ausdruck gefangen werden und einige nicht.
Mein Problem ist, hinterher entscheiden zu müssen, welche dieser Ausdrücke gefangen wurden (etwa per Index oder wie auch immer).

Das Problem klingt so erstmal total blöd, denn wenn die Dinge, die ich da fange gleich sind, warum will ich dann wissen, welches ich da gefangen habe.
Das liegt daran, dass diese Dinge Platzhalter sind für spezielle andere Dinge, die sich unterscheiden können.
In meinem speziellen Fall sind es Datumseinträge (und andere mehrfach vorkommende Dinge) und statt <<A>> steht dort <<date>>.

Hier ein kleines Programm zur Veranschaulichung:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

my $text = "Vorrede bla bla Anfang <<A>> Teil1 <<A>> Teil2 <<B>> Teil3 <<A>> Ende Nachrede.";
my $re = qr~Anfang <<A>> [^<]+ (<<A>>) [^<]+ (<<B>>) [^<]+ <<A>> Ende~;
print "text : [$text]\n",
"re : [$re]\n";

my @allmatch = $text =~ $re;
my ($m1, $m2, $m3) = ($`, $&, $');

print "allmatch: ", Dumper \@allmatch;
print "m1 : [$m1]\n",
"m2 : [$m2]\n",
"m2 : [$m3]\n";


Ausgabe:

Code: (dl )
1
2
3
4
5
6
7
8
9
text    : [Vorrede bla bla Anfang <<A>> Teil1 <<A>> Teil2 <<B>> Teil3 <<A>> Ende Nachrede.]
re : [(?-xism:Anfang <<A>> [^<]+ (<<A>>) [^<]+ (<<B>>) [^<]+ <<A>> Ende)]
allmatch: $VAR1 = [
'<<A>>',
'<<B>>'
];
m1 : [Vorrede bla bla ]
m2 : [Anfang <<A>> Teil1 <<A>> Teil2 <<B>> Teil3 <<A>> Ende]
m2 : [ Nachrede.]


Die Frage ist also eigentlich: Komme ich irgendwie an die Teile zwischen den gematchten Teilen des regulären Ausdrucks heran? Dann könnte ich nämlich ermitteln, welches <<A>> gefangen wurde.

Meine Lösungsidee sieht so aus: Beim Einsetzen der <<A>>s speichere ich eine eindeutige Nummer mit ab. Dann sähe der Satz z.B. so aus:

Code: (dl )
Vorrede bla bla Anfang <<A#14>> Teil1 <<A#8>> Teil2 <<B#1>> Teil3 <<A#9>> Ende Nachrede.


Und dann würde ich die regulären Ausdrücke, mit denen ich diesen Satz teste (das sind sehr sehr viele und die will ich nicht ändern) automatisch vor dem Einsetzen in qr~~ mit

Code: (dl )
$reausdruckstext =~ s~>>~#\\d+>>~g;


überarbeiten, so dass ich hinterher meine Treffer genau identifiezieren kann.

Daraus ergibt sich dann dieses Progrämmchen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

my $text = 'Vorrede bla bla Anfang <<A#14>> Teil1 <<A#8>> Teil2 <<B#1>> Teil3 <<A#9>> Ende Nachrede.';
my $retext = 'Anfang <<A>> [^<]+ (<<A>>) [^<]+ (<<B>>) [^<]+ <<A>> Ende';
print "text : [$text]\n",
"retext : [$retext]\n";

$retext =~ s~>>~#\\d+>>~g;
my $re = qr~$retext~;
print "retext : [$retext]\n",
"re : [$re]\n";

my @allmatch = $text =~ $re;
my ($m1, $m2, $m3) = ($`, $&, $');

print "allmatch: ", Dumper \@allmatch;
print "m1 : [$m1]\n",
"m2 : [$m2]\n",
"m2 : [$m3]\n";


mit der Ausgabe

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
text    : [Vorrede bla bla Anfang <<A#14>> Teil1 <<A#8>> Teil2 <<B#1>> Teil3 <<A#9>> Ende Nachrede.]
retext : [Anfang <<A>> [^<]+ (<<A>>) [^<]+ (<<B>>) [^<]+ <<A>> Ende]
retext : [Anfang <<A#\d+>> [^<]+ (<<A#\d+>>) [^<]+ (<<B#\d+>>) [^<]+ <<A#\d+>> Ende]
re : [(?-xism:Anfang <<A#\d+>> [^<]+ (<<A#\d+>>) [^<]+ (<<B#\d+>>) [^<]+ <<A#\d+>> Ende)]
allmatch: $VAR1 = [
'<<A#8>>',
'<<B#1>>'
];
m1 : [Vorrede bla bla ]
m2 : [Anfang <<A#14>> Teil1 <<A#8>> Teil2 <<B#1>> Teil3 <<A#9>> Ende]
m2 : [ Nachrede.]


Damit wüsste ich hinterher über @allmatch genau, welche der <<A>>s ich gefangen habe.

Gibt es eine einfachere Lösung?
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite

View full thread Problem im Zusammenhang mit REs: kniffelig