Entwickler-Ecke

Programmiersprachen (Server) - regulärer Ausdruck - ungebrauchte Gruppierungen weglassen


Heiko - Sa 13.12.08 19:21
Titel: regulärer Ausdruck - ungebrauchte Gruppierungen weglassen
Hallo,

ich habe momentan folgenden regulären Ausdruck:

Quelltext
1:
{{\s*(\w*)(\s*(\w*)=\s*("\w*"|\w*))*\s*}}                    

Dieser match z.B. von

Quelltext
1:
test{{ name value="asd" test=var}}sadjk                    

alles zwischen den geschweiften Klammern.

Dabei entstehen 4 Gruppen:

Quelltext
1:
2:
3:
4:
   group 1: (\w*)
   group 2: (\s*(\w*)=\s*("\w*"|\w*))
   group 3: (\w*)
   group 4: ("\w*"|\w*)

Wie man jedoch sieht, ist die zweite Gruppe unwichtig, da die ja durch die 3. und 4. abgedeckt wird. Gibt es die Möglichkeit im regEx zu sagen, dass er diese Gruppe nicht zurückgeben soll?

Hintergrund ist der, dass ich mal wieder an einem Templatesystem bastle. Dabei kommt als erstes, was für ein Befehl jetzt folgt. Und anschließend die Parameter, die in der Form var=value angegeben werden sollen. Mich interessiert also nur der Befehl und die Paare (var, value).

Grüße
Heiko


Kha - Sa 13.12.08 20:01

Das wäre doch ein idealer Fall für benannte Gruppen. Da PHP wohl PCRE verwendet, sollten die unterstützt sein: http://www.regular-expressions.info/named.html


BenBE - Sa 13.12.08 20:19

Warum so umständlich: Non-matching groups mit ?: verwenden ;-)


Heiko - Sa 13.12.08 21:00

@Benny: danke, das ist genau das, was ich suchte :)

@Kha: danke für den Tipp. Das man die bennen kann, war mir neu, allerdings wüsste ich nicht, ob es mir hier etwas bringt, oder ob er die named-Tags dann überschreibt, da ich ja verschachtelte ()* habe.


Kha - Sa 13.12.08 21:07

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Warum so umständlich: Non-matching groups mit ?: verwenden ;-)
Weil unbenannte Gruppen grundsätzlich verboten werden sollten :D [meta]wer braucht schon überhaupt Regexes, wenn es niedliche monadische Parser gibt?[/meta]. Wenn man einer Gruppe eine ganz bestimmte Funktion zuordnen will, warum sie dann nicht auch so benennen? Oder ist Groups[1] wirklich so viel aussagekräftiger als Groups["value"] :( ?
Oder stell dir vor, jemand will den Wert vor dem Attributnamen haben *g* .

user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
Das man die bennen kann, war mir neu, allerdings wüsste ich nicht, ob es mir hier etwas bringt, oder ob er die named-Tags dann überschreibt, da ich ja verschachtelte ()* habe.
Zu PCRE kann ich nichts sagen, aber wenn, dann sollte doch mit unbenannten Gruppen genau das gleiche Problem auftreten?


BenBE - Sa 13.12.08 21:20

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Warum so umständlich: Non-matching groups mit ?: verwenden ;-)
Weil unbenannte Gruppen grundsätzlich verboten werden sollten :D [meta]wer braucht schon überhaupt Regexes, wenn es niedliche monadische Parser gibt?[/meta]. Wenn man einer Gruppe eine ganz bestimmte Funktion zuordnen will, warum sie dann nicht auch so benennen? Oder ist Groups[1] wirklich so viel aussagekräftiger als Groups["value"] :( ?
Oder stell dir vor, jemand will den Wert vor dem Attributnamen haben *g* .

Noncapturing groups sind das genaue Gegenteil von von deinen benannten Capturing-Groups. Non-Capturing-Groups erzeugen im Ergebnis des Regexp keine Rückgabe, während normale Gruppierungen teil des Ergebnisses sind.

Beispiel:
Ich möchte caabbbababbbd matchen, brauch aber nur c und d: Also: /(.)(?:a+b+)+(.)/ Natürlich kann ich c und d auch noch benennen ;-)

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
Das man die bennen kann, war mir neu, allerdings wüsste ich nicht, ob es mir hier etwas bringt, oder ob er die named-Tags dann überschreibt, da ich ja verschachtelte ()* habe.
Zu PCRE kann ich nichts sagen, aber wenn, dann sollte doch mit unbenannten Gruppen genau das gleiche Problem auftreten?

PCRE ist bei benannten Gruppen potentiell langsamer im Parsing (Overhead) und benötigt oftmals (speziell bei PHP ;-)) wesentlich mehr Speicher --> Finger weg :P


Heiko - Sa 13.12.08 21:27

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
Das man die bennen kann, war mir neu, allerdings wüsste ich nicht, ob es mir hier etwas bringt, oder ob er die named-Tags dann überschreibt, da ich ja verschachtelte ()* habe.
Zu PCRE kann ich nichts sagen, aber wenn, dann sollte doch mit unbenannten Gruppen genau das gleiche Problem auftreten?

Bei der Standardvariante werden die doch einfach durchnummeriert, also immer verschiedene Namen (Nummern). Wenn ich aber den Namen fest zuweise, gibts es ja keine Unterscheidung mehr.

Ich habs aber gerade mal probiert:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
<?php

echo  "<pre>";
preg_match("/{{\s*(\w*)(\s*(\w*)=\s*(\"\w*\"|\w*))*\s*}}/""test{{ task var1=\"value1\" var2=value2}}sadjk", $result);
print_r($result);
echo  "";
preg_match("/{{\s*(?Ptask=\w*)(\s*(\w*)=\s*(\"\w*\"|\w*))*\s*}}/""test{{ task var1=\"value1\" var2=value2}}sadjk", $result);
print_r($result);
echo  "<pre>";
?>

Irgendwie mag er das mit dem ?P noch nicht ("unrecognized character after (?P"). Habe ich die Quelle da falsch interpretiert? Auch ?Ptaskgroup nimmt er nicht.


BenBE - Sa 13.12.08 21:37

(?P=name) ist eine Back-Referenz, (?P<name>pattern) matcht in eine Named Group. Siehe http://de2.php.net/manual/de/reference.pcre.pattern.syntax.php


Heiko - Sa 13.12.08 21:58

:autsch: ist das eine scheiß Syntax. Wer kommt bitteschön auf die Idee, dass die < > dableiben müssen?

Allerdings kann ich das Problem mit dem named noch nicht testen. php macht es gerade nicht so, wie ich will :(


C#-Quelltext
1:
preg_match('/{{\s*(\w*)(\s*(\w*)=\s*("\w*"|\w*))*\s*}}/'"test{{ task var1=value1 var2=value2}}sadjk", $result);                    

Ergibt nur:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Array
(
    [0] => {{ task var1=value1 var2=value2}}
    [1] => task
    [2] =>  var2=value2
    [3] => var2
    [4] => value2
)

Und nicht wie erwartet:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
Array
(
    [0] => {{ task var1=value1 var2=value2}}
    [1] => task
    [2] =>  var1=value1
    [3] => var1
    [4] => value1
    [5] =>  var2=value2
    [6] => var2
    [7] => value2
)

Hat einer von euch da noch ne Ahnung was los ist? Bzw. wie man das verbessern kann?


BenBE - Sa 13.12.08 22:06

Bei Matches in Schleifen wird nur die zuletzt gematchte Instanz gespeichert.


Kha - So 14.12.08 00:19

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Warum so umständlich: Non-matching groups mit ?: verwenden ;-)
Weil unbenannte Gruppen grundsätzlich verboten werden sollten :D [meta]wer braucht schon überhaupt Regexes, wenn es niedliche monadische Parser gibt?[/meta]. Wenn man einer Gruppe eine ganz bestimmte Funktion zuordnen will, warum sie dann nicht auch so benennen? Oder ist Groups[1] wirklich so viel aussagekräftiger als Groups["value"] :( ?
Oder stell dir vor, jemand will den Wert vor dem Attributnamen haben *g* .

Noncapturing groups sind das genaue Gegenteil von von deinen benannten Capturing-Groups.
Eben :) . Entweder unbenannte Gruppen und dann unwichtige ausschließen durch noncapturing oder named und sich um die restlichen Gruppen gar keine Gedanken mehr machen.

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
PCRE ist bei benannten Gruppen potentiell langsamer im Parsing (Overhead) und benötigt oftmals (speziell bei PHP ;-)) wesentlich mehr Speicher --> Finger weg :P
Pfft, wozu leben wir schon im "throw more CPUs at it"-Zeitalter ;) ?

user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
:autsch: ist das eine scheiß Syntax. Wer kommt bitteschön auf die Idee, dass die < > dableiben müssen?
Irgendein Delimiter muss halt her. Sei froh, dass nicht auch noch geschweifte Klammern eine Bedeutung haben ;) .

user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
Allerdings kann ich das Problem mit dem named noch nicht testen. php macht es gerade nicht so, wie ich will :(
Saach ich doch :) . In der .Net-Implementierung kann man alle Captures einer Gruppe abfragen, nicht nur die letzte, aber wenn das nicht geht, musst du wohl erst einmal alle Tags matchen und für jedes Tag dann noch einmal alle Attribute.


BenBE - So 14.12.08 00:28

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconHeiko hat folgendes geschrieben Zum zitierten Posting springen:
:autsch: ist das eine scheiß Syntax. Wer kommt bitteschön auf die Idee, dass die < > dableiben müssen?
Irgendein Delimiter muss halt her. Sei froh, dass nicht auch noch geschweifte Klammern eine Bedeutung haben ;) .

Doch, haben sie: Anzahlen eingrenzen, wie häufig etwas wiederholt werden soll ;-)