Tom: Reguläre Ausdrücke

Hello,

ich suche ein Muster. Das kann folgendermaßen aussehen

<!--{F-filetime(-10)}-->
   <!--{T-mainmenu}-->
   <!--{L-self}-->

und habe dafür

//              1     2     3        4        5   6   7       7       8   9
    $pattern = '=^(.*?)(<!--{)(.*?)(L-|M-|F-|T-)(.*?)(((.*?)))?([^}]*?)(}-->)(.*$)=msi';

als Pattern aufgebaut, was aber augenscheinlich falsch ist.

Als Rückgabewerte benötige ich z.B.

<!--{F-filetime(-10)}-->
      1    2      3

1 Kennung  ggf. auch ohne den Bindestrich
2 Bezeichner
3 Argumente aus der Klammer, sofern die Klammer vorhanden ist

Wie muss man das nun angeben, dass
a. eine Gruppe von Zeichen {0,1} mal vorhanden sein darf und
b. wenn sie vorhanden ist, ein Suchmuster _enthält_ ?

Da komm ich irgendwie noch nicht weiter...

Harzliche Grüße vom Berg
esst mehr http://www.harte-harzer.de

Tom

--
Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
Nur selber lernen macht schlau
  1. Hello,

    ich suche ein Muster. Das kann folgendermaßen aussehen

    <!--{F-filetime(-10)}-->
       <!--{T-mainmenu}-->
       <!--{L-self}-->

    und habe dafür

    //              1     2     3        4        5   6   7        8         9     10
         $pattern = '=^(.*?)(<!--{)(.*?)(L-|M-|F-|T-)(.*?)(((.*?)))?([^}]*?)(}-->)(.*$)=msi';

    bei 6:   (((.*?)))?

    stürz ich ab...

    Es sollen null oder einmal die Klammern (xxx) vohanden sein. Ich benötige aber auch das Argument

    Da komm ich irgendwie noch nicht weiter...

    Harzliche Grüße vom Berg
    esst mehr http://www.harte-harzer.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Hi,

      bei 6:   (((.*?)))?
      stürz ich ab...

      inwiefern?

      Es sollen null oder einmal die Klammern (xxx) vohanden sein. Ich benötige aber auch das Argument

      Was Du zurück haben möchtest, setzt Du in "(...)". Was Du _nicht_ zurück haben möchtest, setzt Du in "(?:...)". Es lohnt sich, auch die vielen, vielen anderen Gimmicks nachzulesen, die Regular Expressions auf Lager haben.

      Da komm ich irgendwie noch nicht weiter...

      Du hast leider noch nicht beschrieben, was dies bedeutet. Sprich: Dein Problem ist nicht ersichtlich.

      Cheatah

      --
      X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
      X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
      X-Will-Answer-Email: No
      X-Please-Search-Archive-First: Absolutely Yes
      1. Hello,

        bei 6:   (((.*?)))?
        stürz ich ab...

        inwiefern?

        [3] => Array
                (
                    [4] => F
                    [5] =>
                    [6] =>
                    [7] =>
                    [8] => filedate(-10)
                    [9] => }-->

        Das Ergebnis landet eben nicht in [5] und [6], sondern in [8]

        Erwartet hätte ich:

        [3] => Array
                (
                    [4] => F
                    [5] => filedate
                    [6] => (-10)
                    [7] => -10
                    [8] =>
                    [9] => }-->

        Das Patrtern sieht bisher so aus:

        1      2      3      4          5      6   7           8         9     10
          $pattern = '=^(.*?)(<!--\{)(.*?)(L|M|F|T)-([^\(]*?)(\((.*?)\))??([^\}]*?)(\}-->)(.*$)=msi';

        Muss man die geschweiften Klammern eigentlich mittels zweier Backslashes maskieren?
        also:

        (<!--\{)   für das Suchmuster   <!--{

        Die sind doch Metazeichen, oder?

        Es sollen null oder einmal die Klammern (xxx) vohanden sein. Ich benötige aber auch das Argument

        Was Du zurück haben möchtest, setzt Du in "(...)". Was Du _nicht_ zurück haben möchtest, setzt Du in "(?:...)". Es lohnt sich, auch die vielen, vielen anderen Gimmicks nachzulesen, die Regular Expressions auf Lager haben.

        Wo?
        Ich habe schon die wildesten Seiten durch, bin aber noch nicht viel schlauer geworden.
        z.B. http://www.rrz.uni-hamburg.de/RRZ/W.Wiedl/Skripte/CGI-Perl/Regulaere_Ausdruecke/REIntro.htm#1.1

        Gibts eine bessere Seite? Das würde mich freuen!

        Harzliche Grüße vom Berg
        esst mehr http://www.harte-harzer.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Huhu Tom

          Ich habe schon die wildesten Seiten durch, bin aber noch nicht viel schlauer geworden.
          z.B. http://www.rrz.uni-hamburg.de/RRZ/W.Wiedl/Skripte/CGI-Perl/Regulaere_Ausdruecke/REIntro.htm#1.1

          Gibts eine bessere Seite? Das würde mich freuen!

          Auf jeden Fall gibt es noch viele andere Seiten zum Thema.
          Diese beiden finde ich recht gut gelungen:
          http://pcre.nophia.de/explain/index.php
          http://gnosis.cx/publish/programming/regular_expressions.html

          Viele Grüße

          lulu

          --
          bythewaythewebsuxgoofflineandenjoytheday
      2. Hello,

        Was Du zurück haben möchtest, setzt Du in "(...)". Was Du _nicht_ zurück haben möchtest, setzt Du in "(?:...)". Es lohnt sich, auch die vielen, vielen anderen Gimmicks nachzulesen, die Regular Expressions auf Lager haben.

        Das ist jetzt der letzte Stand:

        //              1                    2          3                     4                                   5
            $pattern = '=^(.*?)(?:<!--\{)\s*?(L|M|F|T)-([a-z0-9]{1,})\s*?(?:\((.*?)\))?\s*?(?:[^\}]*?)(?:\}-->)(.*$)=msi';

        Danke für den Tipp mit (?:...)

        Dieses Pattern eignet sich nun hervorragend für den Aufbau einer Template Parse Engine.

        Ich hoffe, dass kein Fehler mehr drinsteckt

        Harzliche Grüße vom Berg
        esst mehr http://www.harte-harzer.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Hi,

          Ich hoffe, dass kein Fehler mehr drinsteckt

          sind die \s richtig, oder müsste es im Kontext \s heißen? Das "?" hinter dem entsprechenden Sternchen ist jedenfalls nicht nötig: Greediness stört Dich hier nicht. Für "L|M|F|T" kannst Du auch "[LMFT]" schreiben; wenn es garantiert einbuchstabig ist, wäre das IMHO zu bevorzugen.

          Cheatah

          --
          X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
          X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
          X-Will-Answer-Email: No
          X-Please-Search-Archive-First: Absolutely Yes
          1. Hello,

            sind die \s richtig, oder müsste es im Kontext \s heißen?

            Es MUSS \s heißen. Hatten wir gestern noch drüber diskutiert (siehe Beitrag von Sven R.)

            Harzliche Grüße vom Berg
            esst mehr http://www.harte-harzer.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
  2. Hallo!

    Also so spontan würde ich sagen, und habe es auch getestet:

    /^<!--{([a-z])-([a-z]{1,})(?(.*))?}-->$/msi

    <!--{F-filetime(-10)}-->

    1. F
    2. filetime
    4. -10

    <!--{T-mainmenu}-->

    1. T
    2. mainmenu
    3. NULL

    <!--{L-self}-->

    1. L
    2. self
    3. NULL

    André Laugks

    --
    Die Frau geht, die Hilti bleibt!
    1. Korrektur:

      <!--{F-filetime(-10)}-->

      1. F
      2. filetime
      3. -10

      <!--{F-filetime(-10)}-->

      1. F
      2. filetime
      3. -10

      André Laugks

      --
      Die Frau geht, die Hilti bleibt!
      1. Hello,

        Korrektur:

        <!--{F-filetime(-10)}-->

        1. F
        2. filetime
        3. -10

        <!--{F-filetime(-10)}-->

        1. F
        2. filetime
        3. -10

        Danke André,
        Das sieht schon sehr gut aus.

        Aber das ist noch nicht "wasserdicht", oder?

        Ich bin im Moment nur etwas irriterit über die Backslashes. Müssten da nicht \ stehen?
        Das ist aber ein PHP-Problem...

        <cite  url(http://de2.php.net/manual/en/language.types.string.php)
        Single quoted
        The easiest way to specify a simple string is to enclose it in single quotes (the character ').

        To specify a literal single quote, you will need to escape it with a backslash (), like in many other languages. If a backslash needs to occur before a single quote or at the end of the string, you need to double it. Note that if you try to escape any other character, the backslash will also be printed! So usually there is no need to escape the backslash itself.
        </cite>

        Ulkigerweise funktionierte auch mein kaputtes Muster (halbwegs) mit oder ohne gedoppelte Backslashes...

        Harzliche Grüße vom Berg
        esst mehr [link:http://www.harte-harzer.de>

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Hallo!

          Aber das ist noch nicht "wasserdicht", oder?

          Hast Du eine Undichtigkeit gefunden?

          Ich verwende "The Regex Coach", kann ich Dir übrigends sehr empfehlen, und habe den regulären Ausdruck darin geschrieben. Ich konnte keine Undichtigkeit fest stellen. Ich habe glaube eventuelle Leerzeichen nicht beachtet, kann man aber noch einbauen.

          Ich bin im Moment nur etwas irriterit über die Backslashes. Müssten da nicht \ stehen?

          Nein, mit dem einen Backslash, wird die Klammer { zu einem "normalen" Zeichen.

          André Laugks

          --
          Die Frau geht, die Hilti bleibt!
  3. Hallo,

    vielleicht habe Dich mißverstanden, aber spricht etwas gegen diese Lösung?:

    <?php
    $str1 = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. <!--{F-filetime(-10)}-->Nunc odio augue.';
    $str2 = '<!--{T-mainmenu}-->';
    $str3 = '<!--{L-self}-->';
    $str4 = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. <!--{F-filetime(-10)}-->Nunc odio augue. <!--{T-mainmenu}-->  <!--{L-self}-->';

    $pattern = '/<!--{(?:.*?)(L|M|F|T)-([a-z]+)(?:(([0-9-]+)))?}-->/msi';

    preg_match($pattern, $str1, $matches1);
    preg_match($pattern, $str2, $matches2);
    preg_match($pattern, $str3, $matches3);
    preg_match_all($pattern, $str4, $matches4, PREG_SET_ORDER);

    while(list($key,$val) = each($matches1)) { echo $key.' = '.$val.'<br />'; }
    echo '<hr />';
    while(list($key,$val) = each($matches2)) { echo $key.' = '.$val.'<br />'; }
    echo '<hr />';
    while(list($key,$val) = each($matches3)) { echo $key.' = '.$val.'<br />'; }
    echo '<hr />';
    while(list(,$match) = each($matches4)) { while(list($key,$val) = each($match)) { echo $key.' = '.$val.'<br />'; } }
    echo '<hr />';
    ?>

    Ciao,
    Andreas

  4. Hello,

    Ich habe die Lösung gefunden:

    ich suche ein Muster. Das kann folgendermaßen aussehen

    <!--{F-filetime(-10)}-->
       <!--{T-mainmenu}-->
       <!--{L-self}-->

    und habe dafür

    //              1     2     3        4        5   6   7       7       8   9
        $pattern = '=^(.*?)(<!--{)(.*?)(L-|M-|F-|T-)(.*?)(((.*?)))?([^}]*?)(}-->)(.*$)=msi';

    als Pattern aufgebaut, was aber augenscheinlich falsch ist.

    1      2      3      4         5           6   7          8         9      10
    $pattern = '=^(.*?)(<!--\{)(.*?)(L|M|F|T)-([a-z0-9]{1,})(\((.*?)\))?([^\}]*?)(\}-->)(.*$)=msi';
                                                ------------

    So funktioniert es, wie vorgesehen. Bezüglich der Toleranz kann ich noch dran arbeiten.

    <!--{ F-filetime ( -10 ) }-->
             ^          ^ ^   ^ ^
    Hier wären dann Leerzeichen möglich, die ich aber nicht als Result benötige.

    Die Frage mit den Backslashes hat sich auch klären lassen, inde ich mir das resultierende Pattern ausgeben lassen habe. Es ist PHP egal, ob man einen \ oder zwei \ nimmt. Es resultiert daraus immer nur einer. Ich habe jetzt, um zum Manual konform zu bleiben, zwei benutzt.

    Das mit [5] habe ich allerdings noch nicht begriffen, wo da der gravierende Unterschied ist.

    Der Sinn der Übung steckt in der Abarbeitung eines Templates.
    Die Vorlage hatte ich hier die letzten Tage im Archiv gefunden.

    In einer externen Datenressource stehen zu den jeweiligen Bezeichneren die Texte, oder aber die Parameter zu Funktionen, die dann ausgeführt werden, sofern sie definiert sind.

    Auf diese Weise lassen sich userkonfigurierbare aktive Templates bauen.
    Den Usern eines CMS kann man schließlich nicht das Benutzen von "include()" und PHP-Code gestatten.
    Man kann auf diese Weise beliebige Funktionen erfinden, deren Ergebnis dann an der jeweiligen Stelle ins Template eingestanzt wird.

    Ich bin durch Eure Hilfe ein großes Stück weitergekommen. Danke allen und zieh mir jetzt nochmal die Klamotten von lulu rein ;-)

    Harzliche Grüße vom Berg
    esst mehr http://www.harte-harzer.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Moin!

      Die Frage mit den Backslashes hat sich auch klären lassen, inde ich mir das resultierende Pattern ausgeben lassen habe. Es ist PHP egal, ob man einen \ oder zwei \ nimmt. Es resultiert daraus immer nur einer. Ich habe jetzt, um zum Manual konform zu bleiben, zwei benutzt.

      Es ist nicht egal. Der Backslash wird ja als Escape-Zeichen bzw. als Einleiter für Sonderzeichen wie \n benutzt.

      Um in einem String selbst einen Backslash zu platzieren, muß er verdoppelt werden: "\" -> \

      Ein einzelner Backslash, der nicht mit einem nachfolgenden Zeichen zu einer Sonderfunktion geführt werden kann, bleibt aber als einzelnes Zeichen erhalten.
      "\n" -> chr(10)
      "\z" -> \z

      Du solltest also dringend das Escaping des Strings mit berücksichtigen, um nicht unerwartet in irgendwelche Fallen zu tappen. Die Regex-Engine will zum Escapen von Punkten beispielsweise . erhalten, um diesen String aber in PHP in den Programmcode einzugeben, ist "\." notwendig. Arbeitest du nur mit ".", funktioniert das aufgrund der fehlenden Sondereigenschaften des Zeichens . so, wie erwartet - aber wehe, du ersetzt den Punkt durch z.B. ein n...

      - Sven Rautenberg

      1. Hello Sven,

        Du solltest also dringend das Escaping des Strings mit berücksichtigen, um nicht unerwartet in irgendwelche Fallen zu tappen. Die Regex-Engine will zum Escapen von Punkten beispielsweise . erhalten, um diesen String aber in PHP in den Programmcode einzugeben, ist "\." notwendig. Arbeitest du nur mit ".", funktioniert das aufgrund der fehlenden Sondereigenschaften des Zeichens . so, wie erwartet - aber wehe, du ersetzt den Punkt durch z.B. ein n...

        Danke nochmal für die Stellungnahme. Ich habe es auch so gemacht, da es erstens in der PHP-Doku so beschrieben war und ich zweitens auch auf "Nummer sicher" gehen wollte. An dieser Stelle ist PHP wohl von Mircrosoft beeinflusst ;-) (Tolerante Auslegung der Sonderfunktion des \ )

        Das bedeutet aber auch für die anderen Lösungen in diesem Thread, dass sie an genau dieser Stelle kneifen... Müssten also auch alle mit \ arbeiten :-)

        Harzliche Grüße vom Berg
        esst mehr http://www.harte-harzer.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau