Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
29.11.2005, 23:42
thinktank



Hi,

Mein Problem ist eher allgemeiner Natur, aber die Lösung sollte in PHP sein. Wie kann ich Blöcke von while, if - Anweisungen etc. in der richtigen Reihenfolge durchgehen?

Ich brauche das für eine Templateklasse, die auch Schleifen beherrschen soll. Blöcke meiner Schleifen habe ich bis jetzt mit der RegExp Quellcode:{LOOP[^\}]+\}(.*)\{ENDLOOP\} erkennen lassen. Hier wird schnell klar: Das funktioniert nur in einer bestimmten Konstellation.

Beispiel:
Folgender Code soll geparst werden:
Quellcode:LOOP // {

LOOP
ENDLOOP

LOOP

  LOOP
  ENDLOOP

ENDLOOP
ENDLOOP // }

LOOP
ENDLOOP
Mit der oberen RegExp (die ja greedy ist), trifft der ganze code zu, also vom ersten LOOP bis zum letzten ENDLOOP. Wenn ich aber die RegExp nicht greedy mache, trifft der Bereich vom ersten LOOP bis zum ersten ENDLOOP zu, aber eigentlich will ich den Block von '{' bis '}'.
Ist dies überhaupt mit RegExp zu lösen?

Suche derzeit in diversen Templateklassen (wie z.B. Smarty) nach der entsprechenden Zeile. Für Hinweise wäre ich dankbar.

Danke!

thinktank

--


Dieser Beitrag wurde am 29.11.2005 um 23:42 von thinktank bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
001
30.11.2005, 15:08
theDon



Recursive Matching ist dein Freund. Aber mach das nur, wenn die Inhalte aus vertrauenswuerdigen Quellen kommen. Fuer Templates ist das in Ordnung, aber Userdata solltest du da nicht durch jagen, weil das unter Umstaenden massivst imperformant ist.

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
002
30.11.2005, 22:30
thinktank



Ok, Danke für den Tipp. Ich glaube, ich habe auf http://www.perl.com/pub/a/2003/06/06/regexps.html unten bei "How do I extract parenthesized text?'" die Lösung gefunden. Scheint zumindest mit RegEx nicht anders zu gehen, da iterative Lösung nicht funktionieren. Wenn ich den passenden Code für mein Problem habe, werde ich den ggf. hier reinschreiben.

--

zum Seitenanfang zum Seitenende Profil || Suche
003
03.12.2005, 21:42
thinktank



In Perl scheint die Lösung mit rekursiven RegEx einfach:

Quellcode:# von http://www.perl.com/pub/a/2003/06/06/regexps.html
    $paren = qr/
      \(
        (
           [^()]+  # Not parens
         |
           (??{ $paren })  # Another balanced group (not interpolated yet)
        )*
      \)
    /x;
Aber wie implemtiere ich so was in PHP? Schwierigkeiten macht vor allem der Operator "??{ }", also dass das Matching der RegEx $paren erst dann ausgeführt wird, wenn die Alternative erreicht wird.

--

zum Seitenanfang zum Seitenende Profil || Suche
004
03.12.2005, 21:57
theDon



Zitat:
Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. Perl 5.6 has provided an experimental facility that allows regular expressions to recurse (among other things). The special item (?R) is provided for the specific case of recursion. This PCRE pattern solves the parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored): \( ( (?>[^()]+) | (?R) )* \)
http://de2.php.net/manual/en/reference.pcre.pattern.syntax.php

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
005
06.12.2005, 17:36
thinktank



Der Fairness halber, jetzt meine Lösung.

Erst durch ein str_replace eine Klammer vor jedes LOOP und nach jedem ENDLOOP setzen. Das ist vielleicht nicht zwingend notwendig, aber in meinen Augen besser als mit Lookaheads oder Lookbehinds zu arbeiten. Vielleicht isses auch nicht so rechenlastig. Wer kurz dazu ein Statement abgeben könnte ...:)

Quellcode:$template= str_replace("<LOOP", "{<LOOP", $template);
$template = str_replace("ENDLOOP>", "ENDLOOP>}", $template);
Danach nen preg_match mit dem angesprochenen rekursiven Matching:

Quellcode:preg_match("/\{ (( (?>[^{}]+) | (?R) )*) \}/Ux", $template, $loop);
Das \U für Ungreedy ist notwendig, damit ich den ganzen Loop als Match bekomme.

--

zum Seitenanfang zum Seitenende Profil || Suche
006
10.12.2005, 20:45
scus



mal ne kleine frage: was wäre, wenn man statt { und } als "blockumrandung" '<block>' und '</block>' nehmen wollte, weil man { und } anderweitig verwendet? kann man irgendwie ganze strings invertieren? [^<block>] würde schließlich <, b, l, o, c, k, > jeweils einzeln invertieren...

--

sincères amitiés scus
--
Tand, Tand ist das Gebilde von Menschenhand

zum Seitenanfang zum Seitenende Profil || Suche
007
10.12.2005, 21:09
HammerBlade



Wie wärs mit [^<][^b][^l][^o][^c][^k][^>]? Scherz bei seite.

Die Kommentare auf php.net sind oft nützlich: http://de2.php.net/manual/en/function.preg-grep.php#55421

--

"Mit C++ (noch besser mit C) kann man sich _sehr_ leicht in den Fuss schiessen." - theDon
Auspack und freu! - Auszug aus einer, aus dem japanischen übersetzten, Bedienugsanleitung für ein Spielzeugaquarium.
--
Photon Audio Player | Majestic42.net | How To Ask Questions The Smart Way

zum Seitenanfang zum Seitenende Profil || Suche
008
10.12.2005, 22:02
scus



danke, das hat funktioniert... hier mal mein code um die blöcke zu finden.
PHP-Quellcode:<?php
$this
->RegName '[a-zA-Z0-9_-~]+';

function 
_getBlocks() {
        if(
preg_match_all('/<block:('.$this->RegName.')> (( (?> ((?:(?!<block:('.$this->RegName.')>).)+) ) | (?R) )*) <\/block>/Uxs'$this->_Content$matchPREG_SET_ORDER)) {
            foreach(
$match as $t_match) {
                
$this->_Blocks[$t_match[1]] = array(
                        
'Content' => $t_match[2],
                        
'Parsed' => ''
                    
);
                
$this->_Content str_replace($t_match[0], '<block_parsed:'.$t_match[1].'>'$this->_Content);
            }
        }
}
?>

--

sincères amitiés scus
--
Tand, Tand ist das Gebilde von Menschenhand

zum Seitenanfang zum Seitenende Profil || Suche
009
10.12.2005, 23:02
theDon



Zitat:
HammerBlade postete
Wie wärs mit [^<][^b][^l][^o][^c][^k][^>]? Scherz bei seite.
Lookahead ist dein Freund. `(?!<block>)'

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
010
01.02.2006, 14:40
scus



Neue Frage zum Thema PCRE
Warum gibt folgender Code 1 zurück?
PHP-Quellcode:<?php
preg_match
('/^([a-zA-Z0-9.-_]+)$/''foo/bar');
?>
Nehme ich den Unterstrich ('_') raus, gibt mir die Zeile 0 zurück, so wie erwahrtet.
Warum?

--

sincères amitiés scus
--
Tand, Tand ist das Gebilde von Menschenhand

zum Seitenanfang zum Seitenende Profil || Suche
011
01.02.2006, 14:58
theDon



.-_ ist der Bereich von ,.' bis ,_'. Da liegt allerdings der halbe Zeichensatz dazwischen...

PHP-Quellcode:<?php
preg_match
('/^([a-zA-Z0-9._-]+)$/''foo/bar');
?>
Das tut das, was du willst.

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
012
01.02.2006, 22:00
thinktank



Achja, wo ich gerade sehe, dass der Thread noch genutzt wird: KRegExpEditor hat mir viel geholfen. Stellt den Ausdruck sprachlich und graphisch dar. So hätte man z.B. den obigen Fehler schnell gefunden. Vielleicht gibts ja nen Windows-Port.

--

zum Seitenanfang zum Seitenende Profil || Suche
013
01.02.2006, 23:36
scus



Zitat:
theDon postete
.-_ ist der Bereich von ,.' bis ,_'. Da liegt allerdings der halbe Zeichensatz dazwischen...
Jetzt wo du's sagst ist es logisch! Danke... Werd mal nach diesem Editor gucken.

--

sincères amitiés scus
--
Tand, Tand ist das Gebilde von Menschenhand

zum Seitenanfang zum Seitenende Profil || Suche