suit: erkennen ob PCRE "\p{L}" verfügbar ist

Ich hab' aktuell folgende beiden Ausdrücke um Zeichenketten in Wörter aufzutrennen - ja, nicht perfekt, aber ist nur zum Testen - Problem liegt anderswo :)

preg_match_all('/\p{L}+/u', $str, $arr);  
preg_match_all('/\w+/u', $str, $arr);

Führe ich auf einem System ohne \p-Unterstützung ersteren Ausdruck aus, erhalte ich folgende Fehlermeldung:

Warning: preg_match_all() [function.preg-match-all]: Compilation failed: support for \P, \p, and \X has not been compiled [...]

Das ist natürlich nicht cool :)

Nun möchte ich einen Fallback schaffen, ist \p nicht verfügbar wird der andere Ausdruck verwandt.

mit @ die Fehlerausgabe abfangen und auswerten ist eine Möglichkeit, allerdings wäre eine feine und saubere Lösung interessanter.

Gibt's hier ggf. eine Funktion die ich noch nicht kenne - etwa wie filter_list() wo ich die möglichen vorhandenen Filter für filter_var() überprüfen kann.

Für andere Vorschläge bin ich natürlich auch offen.

  1. Hi!

    Nun möchte ich einen Fallback schaffen, ist \p nicht verfügbar wird der andere Ausdruck verwandt.
    mit @ die Fehlerausgabe abfangen und auswerten ist eine Möglichkeit, allerdings wäre eine feine und saubere Lösung interessanter.

    Was soll daran nicht sauber sein, Fehlermeldungen auszuwerten?

    Gibt's hier ggf. eine Funktion die ich noch nicht kenne

    Da es ein PCRE-spezifisches Thema ist, müsste es da eine Funktion geben. Gibt es aber nicht. Auch phpinfo() sagt darüber nichts.

    Lo!

    1. Was soll daran nicht sauber sein, Fehlermeldungen auszuwerten?

      Ich hab mich vielleicht etwas unglücklich ausgedrückt, natürlich ist es sauber die Fehlermeldung entsprechend auszuwerten :)

      Ich wollte nur wissen, ob ich hier ggf. etwas übersehen habe - also eine noch bessere Sache :)

      Da es ein PCRE-spezifisches Thema ist, müsste es da eine Funktion geben. Gibt es aber nicht. Auch phpinfo() sagt darüber nichts.

      Dachte ich mir, ich hab' nämlich auch nichts gefunden. Danke für die Bestätigung.

  2. Hallo erstmal!

    Ich hab' aktuell folgende beiden Ausdrücke um Zeichenketten in Wörter aufzutrennen - ja, nicht perfekt, aber ist nur zum Testen - Problem liegt anderswo :)

    preg_match_all('/\p{L}+/u', $str, $arr);

    preg_match_all('/\w+/u', $str, $arr);

    
    >   
    >   
    > Führe ich auf einem System ohne \p-Unterstützung ersteren Ausdruck aus, erhalte ich folgende Fehlermeldung:  
    >   
    > Warning: preg\_match\_all() [function.preg-match-all]: Compilation failed: support for \P, \p, and \X has not been compiled [...]  
    >   
    > Das ist natürlich nicht cool :)  
      
    Doch, das ist sogar sehr "cool". Wie zu sehen ist, wird das Script nicht mit einem Fatal Error abgebrochen. Denn; was macht man, wenn man sich nicht sicher ist, ob etwas so funktioniert, wie man es selbst plante? Man guckt nach, ob die gewünschte Wirkung einsetzte. Das aber ginge nicht, wenn das Script abbrach.  
     Zwei Optionen hast Du jedenfalls. Zum einen kannst Du mit einem Test eine Zeichenkette mit beiden Varianten durchlaufen lassen und `$arr`{:.language-php} vergleichen und im weiteren Steuerfluss darauf bedingt (if-else) Rücksicht nehmen. Zum anderen kannst Du die Fehlerbehandlung von PHP nutzen, um Dein Problem zu meistern:  
      
    ~~~php
    function p_fehler($a,$b,$c,$d,$e){  
    	/* print_r(array($a,$b,$c,$d,$e));  
      
    	   zum angucken, was da alles feines übergeben wird, um später  
    	   richtig zu prüfen. Im Folgenden nehme ich einfach  
    	   E_COMPILE_WARNING, weil es das vermutlich trifft. Generell  
    	   ist nur auf den Fehlercode, hier $a, verlass. Fehlermeldungs-  
    	   texte sind nicht zur Überprüfung geeignet!  
    	*/  
    	if($a==E_COMPILE_WARNING){  
    		preg_match_all('/\w+/u', $GLOBALS['str'], $GLOBALS['arr']);  
    	}  
    	/* return(false);  
      
    	   falls die Fehlerausgabe benötigt wird, muss dieser call back  
    	   FALSE zurückgeben!  
    	*/  
    }  
    set_error_handler('p_fehler');  
    preg_match_all('/\p{L}+/u', $str, $arr);  
    restore_error_handler();
    

    Gruß aus Berlin!
    eddi

    1. Das ist natürlich nicht cool :)

      Doch, das ist sogar sehr "cool".

      Ich meinte damit, dass es nicht cool ist wenn eine einzelne Option nicht verfügbar ist, das restliche Script versagt ;) dass es eine Warnung bzw. eine Fehler gibt ist sehr cool :p

      Zwei Optionen hast Du jedenfalls. Zum einen kannst Du mit einem Test eine Zeichenkette mit beiden Varianten durchlaufen lassen

      Das muss ich garnicht - es würde eine eine reichen

      $teststring = "維 foo";
      wenn ein preg_match_all auf diesen String im Key 0 wieder "維" zurückliefert, funktioniert der Ausdruck - alles im Butter. Es ist garnicht notwendig, dass ich beide vergleiche.

      Ich fürche aber, dass das in Summe zeitintensiver ist, als die Fehlermeldung auszuwerten.

      Das fällt aber bereits in den Bereich der Mikrooptimierung - da die ob das ein paar ms mehr oder weniger benötigt ist für diesen Anwendungsfall nicht relevant, landet nach der Ausführung ohnehin im Cache.

      1. Re:

        $teststring = "維 foo";
        wenn ein preg_match_all auf diesen String im Key 0 wieder "維" zurückliefert, funktioniert der Ausdruck - alles im Butter. Es ist garnicht notwendig, dass ich beide vergleiche.

        Ich fürche aber, dass das in Summe zeitintensiver ist, als die Fehlermeldung auszuwerten.

        Diese Befürchtung teile ich nicht. Wie ja zu sehen war, ist error-handling mit PHP erheblich aufwändiger, was den Gebrauch in einem Script und bei der Wartung derer das Verständnis anbelangt, als ein einfacher Test a la $pattern=(@preg_match_all('/\p{L}+/u', "維 foo", $arr)!==flase) ? '/\p{L}+/u' : '/\w+/u'; preg_match_all($pattern, $str, $arr);`

        Gruß aus Berlin!
        eddi

        1. Diese Befürchtung teile ich nicht. Wie ja zu sehen war, ist error-handling mit PHP erheblich aufwändiger, was den Gebrauch in einem Script und bei der Wartung derer das Verständnis anbelangt, als ein einfacher Test a la $pattern=(@preg_match_all('/\p{L}+/u', "維 foo", $arr)!==flase) ? '/\p{L}+/u' : '/\w+/u'; preg_match_all($pattern, $str, $arr);`

          In diesem Fall muss preg_match_all aber in jedem Fall zweimal ausgeführt werden, beim Auswerten der Fehlermeldung im Idealfall einmal, ansonsten zweimal.

          1. Re:

            Diese Befürchtung teile ich nicht. Wie ja zu sehen war, ist error-handling mit PHP erheblich aufwändiger, was den Gebrauch in einem Script und bei der Wartung derer das Verständnis anbelangt, als ein einfacher Test a la $pattern=(@preg_match_all('/\p{L}+/u', "維 foo", $arr)!==flase) ? '/\p{L}+/u' : '/\w+/u'; preg_match_all($pattern, $str, $arr);`

            In diesem Fall muss preg_match_all aber in jedem Fall zweimal ausgeführt werden, beim Auswerten der Fehlermeldung im Idealfall einmal, ansonsten zweimal.

            Das ist zwar richtig, jedoch räkelt sich seit der Version 5.3 die Anbindung an die PCRE-lib eh im stack 'rum...
            Da macht es dann eher Sinn, sich zu fragen wofür Reguläre Ausdrücke tatsächlich konzipiert sind. Sie bieten ähnlich SQL eine Anbindung an einen Dienst. Dabei muss das Programm für unterschiedliche "Anfragen" nicht geändert werden. Dieses fungiert also als wrapper. Das ist zwar konträr zum Verständnis der PHP-Devs und der Pflicht PCRE untrennbar in PHP einzukompilieren, jedoch sollte man sich klar machen, dass Reguläre Ausdrücke von sich aus Eierlegende Wollmilchsäue sind. Die Frage nach Redundanz stellt sich also bereits durch den Gebrauch an sich — nicht so sehr beim Wiederholungsfall.

            Gruß aus Berlin!
            eddi

            1. In diesem Fall muss preg_match_all aber in jedem Fall zweimal ausgeführt werden, beim Auswerten der Fehlermeldung im Idealfall einmal, ansonsten zweimal.

              So geht's auch und erfüllt seinen Zweck - wenn nun der Fehler aber einen anderen Grund hat als die fehlenden Unicode-Properties, wird trotzdem der Fallback verwandt.

              if(@preg_match_all('/\p{L}+/u', $str, $arr) === false) {  
              	preg_match_all('/\w+/u', $str, $arr);  
              }
              

              Das ist zwar richtig, jedoch räkelt sich seit der Version 5.3 die Anbindung an die PCRE-lib eh im stack 'rum...

              Das Script muss leider auch auf älteren Schinken laufen - vorrangig PHP 5.1.x auf RHEL und CentOS :)

              1. Re:

                Das Script muss leider auch auf älteren Schinken laufen - vorrangig PHP 5.1.x auf RHEL und CentOS :)

                Da machen Deine Überlegungen dann tatsächlich Sinn; war doch jahrelang mein Hauptargument gegen RegEx deren unsägliches »Tempo«. ^^

                Schönes Wochenende noch!
                eddi