Matze: mehrere RegExp oder besser zusammenfügen?

Hallo!

Ich hatte ein einfaches Formular für ein simples Forum ähnlich dem hier.
Zum Anzeigen der Einträge aus der Datenbank reichte mir (bzw. den usern) lange ein 1-Zeiler:

echo '<p class="content" id="content_'.htmlspecialchars($fetch['content_id']).'">'.stripslashes(nl2br(htmlspecialchars($fetch['content']))).'</p>';

Jetzt hätten die Benutzer aber gern ein wenig BB-Code, also habe ich ein paar RegExp geschrieben um den Text bei der Ausgabe zu formatieren:

### Content in HTML-Kontext bringen ####  
$content_formated = stripslashes(nl2br(htmlspecialchars($fetch['content'])));  
  
## Links formatieren  
$content_formated = preg_replace("#\[link=(.*?)\](.*?)\[/link\]#si", '<a href="\1">\2</a>', $content_formated);  
  
## Bilder formatieren  
$content_formated = preg_replace("#\[img=(.*?)\](.*?)\[/img\]#si", '<img src="\1" alt="\2" title="\2"/>', $content_formated);  
  
## Fetten Text formatieren  
$content_formated = preg_replace("#\[f\](.*?)\[/f\]#si", '<b>\1</b>', $content_formated);  
  
## Kursiven Text formatieren  
$content_formated = preg_replace("#\[k\](.*?)\[/k\]#si", '<i>\1</i>', $content_formated);  
  
## Unterstrichenen Text machen  
$content_formated = preg_replace("#\[u\](.*?)\[/u\]#si", '<u>\1</u>', $content_formated);  
  
### Content einfügen ###  
echo '<p class="content" id="content_'.htmlspecialchars($fetch['content_id']).'">'.$content_formated.'</p>';

Jetzt meine Fragen dazu.
Wie performant ist das eigentlich? Ich denke ich werde noch andere Elemente hinzufügen, z.B. Listen. Die Liste wird also noch länger.

Liesse sich das performanter Gestalten indem man die RegExp zusammenfasst?
Wird es dann nicht reichlich unübersichtlich?
Achja und ich hatte schon Mühe bei der ersten RegExp für die Links, die anderen hab ich nur noch davon abgeleitet.
Könntet ihr mir auch ein Beispiel für die Zusammengefassten RegExp geben, für den Fall, dass es sinnvoller ist als meine Lösung?

Vielen Dank!

Grüße, Matze

  1. Liesse sich das performanter Gestalten indem man die RegExp zusammenfasst?
    Wird es dann nicht reichlich unübersichtlich?

    unwartbar und nein. Die Gefahr ist zu gross dass du eine pathologische Regex baust.
    Ich arbeite in Perl mit Callback Funktionen.

    Hier der Parser für das eHF-CMS

    sub parse_function{  
      my $t=shift || '';  
      my $l=shift || 0;  
      for($t){  
        s#(?<!\\)\[get:(theme|layout|version|loginform)(?<!\\)\]#user_get($1)#exg;  
        s#(?<!\\)\[footnote:($Nested1Level)(?<!\\)\]# user_footnote($1) #egx;  
        s#(?<!\\)\[link: ($Nested1Level) (?<!\\)\]# user_link($1) #egx;  
        s#(?<!\\)\[mailtolink: ($Nested1Level) (?<!\\)\]# user_mailtolink($1) #egx;  
        s#(?<!\\)\[image: ($Nested1Level) (?<!\\)\]# user_image($1) #egx;  
        s#(?<!\\)\[navigation: ($Nested1Level) (?<!\\)\]# user_navigation($1) #egx;  
        s#\\\[#[#g;  
        s#\\\]#]#g;  
      }  
      return $t;
    

    }

    Die callback funktionen können dann die Details herausziehen.
    Wichtig ist, dass die API solcher Funktionen upgradebar ist ohne bisherigen Code zu gefährden.

    In BdE-Online umfasst die Liste etwa 30 Funktionen.
    Dabei konnte ich keine Performance-Probleme feststellen, auch nicht bei sehr intensivem Gebrauch.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Hallo Beat!

      Ich arbeite in Perl mit Callback Funktionen.
      Hier der Parser für das eHF-CMS

      Leider versteh ich nicht viel von PERL und weiß weder was sub noch my bedeuten.
      Ich denk mal mit sub wird eine Fubktion, mit my eine Variable deklariert.
      Aber ich weiß nicht was $t=shift || ''; bedeutet. $l kommt ausser in der 3ten Zeile gar nicht mehr vor.

      Könntest du mir bitte deinen Code nochmal erklären?

      Grüße, Matze

      1. Leider versteh ich nicht viel von PERL und weiß weder was sub

        sub ist das Äquivalent zu function in JS

        noch my bedeuten.

        my ist das Äquivalent zu var in JS (allerdings mit Block Scoping)

        Ich denk mal mit sub wird eine Fubktion, mit my eine Variable deklariert.

        jupp

        Aber ich weiß nicht was $t=shift || ''; bedeutet.

        Perl übergibt einer Funktion eine flache Liste
        shift() holt das erste Element aus der Liste.

        Die Zeile bedeutet: weise $t das erste definierte Element der Liste oder '' zu.
        ausführlicher
        $t = shift @_; // @_ ist die Übergabeliste in Perl
        $t ||= ''; $t ist definiert oder es wird '' zugewiesen.

        $l kommt ausser in der 3ten Zeile gar nicht mehr vor.

        gut beobachtet. Ist ein Überbleibsel

        Könntest du mir bitte deinen Code nochmal erklären?

        Das wesentliche ist, dass du eine callback Funktion verwendest.
        Der Code war nicht als Vorlage gedacht, sondern lediglich das Prinzip zu zeigen.

        in Php  heisst es halt dann ungefähr...
        function parser( $text ){
            preg_replace( "some(capuring)pattern", some_callback_func($1), $text );
        }
        function some_callback_func($1) ( $text ){
          // ziehe hier die Details aus dem Text
        }

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
        1. Hallo Beat!

          Könntest du mir bitte deinen Code nochmal erklären?
          Das wesentliche ist, dass du eine callback Funktion verwendest.
          Der Code war nicht als Vorlage gedacht, sondern lediglich das Prinzip zu zeigen.

          So hab ich das auch verstanden ;)

          in Php  heisst es halt dann ungefähr...
          function parser( $text ){
              preg_replace( "some(capuring)pattern", some_callback_func($1), $text );
          }
          function some_callback_func($1) ( $text ){
            // ziehe hier die Details aus dem Text
          }

          Mh wenn ich der Funktion parser() jetzt den Text übergebe...
          wie soll ich das verstehen: preg_replace( "some(capuring)pattern"?
          Also muss ich alle meine RegExp in ein Array schreiben und dann durch das nächste Array ersetzen?
          Also müssten in Array 1 mein BBCode und in Array 2 meine RegExp stehn?
          Was soll $1 für einen Inhalt haben?
          Und ist es wirklich sinnvoll anstatt X mal 1 Funktion X mal 3 Funktionen aufzurufen?
          Irgendwie blick ich jetzt gar nicht mehr durch :(

          Grüße, Matze

          1. Mh wenn ich der Funktion parser() jetzt den Text übergebe...
            wie soll ich das verstehen: preg_replace( "some(capuring)pattern"?
            Also muss ich alle meine RegExp in ein Array schreiben und dann durch das nächste Array ersetzen?

            Wobei in den Ersatzarrays dann die Callback-Funktionsaufrufe gelistet wären.

            Also müssten in Array 1 mein BBCode und in Array 2 meine RegExp stehn?

            PHP Docu
            mixed preg_replace_callback ( mixed $Suchmuster, callback $Callback, mixed $Zeichenkette [, int $Limit [, int &$Anzahl]] )

            Im ersten Array hast du doch die Regex Definitionen.
            Im zweiten die Ersatzbehandlung, also die Liste der Ersatzmuster bzw callbackfunktionen.
            Im dritten parameter hast du dann den zu bearbeitenden Quellinput.

            Was soll $1 für einen Inhalt haben?

            komme darauf zurück

            Und ist es wirklich sinnvoll anstatt X mal 1 Funktion X mal 3 Funktionen aufzurufen?

            nicht x mal 3.
            Und ja, es ist sinnvoll.

            Schau. Zuerst blödes Design.

            [link=http://example.org]Label[/link]
            "/[link=(.*?)](.*?)[/link]/"

            was ist daran blöde? Später fällt dir ein, dass du auch ein hreflang oder ein rel Attribut erlauben willst.
            Du darfst die Syntax aber nicht brechen, denn der Code wurde so und so oft verwendet. Kurz, das ist nicht extensibel und die Rex zu matchen fällt kompliziert aus, wenn du auch noch target, rel hreflang matchen willst..

            Gutes Design.

            [func:
             [par1:val]
             [par2:val]
            ]

            Paradigma 1: Die Reihenfolge der Parameter ist egal
            Paradigma 2: Whitespace zwischen parametergruppen ist zur Übersichtlichkeit
            erlaubt.
            Paradigma 3: Alle Parameter sind optional (es gibt einen defaultwert für alles.)

            So das geht jetzt nicht mehr mit einer einfachen REX.
            hier brauch es eine Callbackfunktion, deren Aufgabe darin besteht, die Parameter herauszuziehen.

            $test =~ s/ [link:($balanced_parameters_1_level)] / user_link($1) /egx

            Was ist in $1? Es ist die Liste aller Parameter. Und diese kann ich jetzt in der Callbackfunktion herausziehen, ohne dass die Reihenfolge der Parameter eine Rolle spielt.
            Ich kann in der Callbackfunktion alles machen, was ich will.
            Und vor allem. Ich kann den Funktionsumfang stetig erweitern, ohne dass ich bestehenden BB-Code breche.

            mfg Beat

            --
            ><o(((°>           ><o(((°>
               <°)))o><                     ><o(((°>o
            Der Valigator leibt diese Fische
  2. Fetten Text formatieren

    $content_formated = preg_replace("#[f](.*?)[/f]#si", '<b>\1</b>', $content_formated);

    Kursiven Text formatieren

    $content_formated = preg_replace("#[k](.*?)[/k]#si", '<i>\1</i>', $content_formated);

    Unterstrichenen Text machen

    $content_formated = preg_replace("#[u](.*?)[/u]#si", '<u>\1</u>', $content_formated);

    Vielleicht noch nicht bei drei Zeilen aber bei etwas so Gleichartigem könnte man noch zusammenfassen und nur die veränderlichen Teile ersetzen.
    das:
    $suchen   = array('f', 'k', 'u');
    $ersetzen = array('b', 'i', 'u');
    finde ich sehr übersichtlich und es läßt sich einfach ergänzen. Nur mit den Kommentaren wird es dann unhandlich.

    Ansonsten halte ich es in etwa wie Beat.