Regexpr nur ein "Punkt" in String darf vorhanden sein

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #16
    Erstmal: Prosit Neujahr, alle miteinander!

    Original geschrieben von ghostgambler
    Lieber 3 String-Funktionen auf einen String als einen Regex von einer Zeile Länge.
    (Wieso kommt mir jetzt der Spruch "Lieber [aA]rm dran, als Arm ab!" in den Sinn ... ;-))

    Mhmmm, mal sehen:

    Du fragst 4 Bedingungen ab, die du über drei Zeilen verteilst, ich nur eine auf einer Zeile.

    Wenn wir mal nur die "Kernabfragen" vergleichen:

    strspn($string, "abcdefghijklmnopqrstuvwxyz0123456789_.") == $len;
    vs.
    preg_match('/\A(?=[^\.]{0,10}(?:\.[^\.]{0,10})?)[a-z0-9_.]{4,10}\z/', $string);

    Okay, du hast 13 Tastendrücke gespart. ;-)
    Probleme bekämst du nur, wenn sich die Anforderung ändern würde, und bspw. zusätzlich Großbuchstaben erlaubt werden würden.

    Nebenbei könnte man den PCRE natürlich auch umbrechen und Newbie-tauglich formatieren. Guckst du hier:
    PHP-Code:
    $pcre '/\A                          # am Anfang verankern
        (?=[^\.]{0,10}(?:\.[^\.]{0,10})?) # maximal ein Punkt darf vorhanden sein[1]
                                          # UND
        [a-z0-9_.]                        # nur die Zeichen a--z, 0--9, _ und . dürfen vorkommen
        {4,10}                            # es dürfen 4--10 Zeichen sein, 
        \z/x'
    ;                           // am Ende verankern
    /* 
    für noch genauere Erläuterungen siehe PCRE-Manual zu 
    Lookahead-Assertions "(?=...)" und  
    "non-capturing subpatterns" (?:...)".
    */ 
    Entwicklungs-Kosten sind deutlich höher als Hardware-Kosten.
    Ja, da scheiden sich die Geister. Es ging mir auch mehr darum, denen, die immer noch das uralte Vorurteil "PCRE sind laaaangsam" vor sich hertragen, zu zeigen, dass das nicht immer so sein muss. Zum Teil hat wohl die ereg-Funktionsfamilie in PHP zu diesem Vorurteil beigetragen.

    Wenn du aber schon von Entwicklungsaufwand (oder -kosten) sprichst, bedenke: Ein PCRE ist einfacher portierbar als ein Haufen byte-orientierter String-Funktionen, die sich so fast nur in PHP finden. Der PCRE dagegen lässt sich 1:1 in alle Sprachen übernehmen, die die PCRE-Lib ansprechen können, z.B. C(++), Objective-C, Delphi/FreePascal, RealBasic, was-weiß-ich-nicht-noch-alles ... und Perl sowieso.

    Nach diesem Lieber-Hardwarekosten-statt-Softwarekosten-Paradigma wären alle C- und erst recht C++-Programmierer arbeitslos. Und ich halte Hardware immer noch für eine physisch begrenzte Ressource. Dass das heut zu Tage gerne anders gesehen wird, ist mir aber schon klar. ;-)

    Es geht übrigens auch ganz ohne preg:
    PHP-Code:
    function check($string) {
      
    $len strlen($string);
      return 
    $len >= && $len <= 10
        
    && strpos($string".") === strrpos($string".")
        && 
    strspn($string"abcdefghijklmnopqrstuvwxyz0123456789_.") == $len;

    Danke, strspn() war die Funktion, die ich gesucht, aber nicht gefunden hatte -- um die Funktion des Regulären Ausdruckes rein String-Funktionen-basiert zu machen. Sie scheitert allerdings spätestens bei Umlauten an der Unicode-Hürde, wo wir dann wieder bei den Entwicklungskosten wären ... ;-)

    Original geschrieben von CadEx
    Diese Idee mit dem strpos() === strrpos() finde ich echt kreativ!

    Aber könnte man nicht einfach ein substr_count() == 1 machen?
    Oder hat die andere Variante irgendwelche Vorteile?
    Sie prüft ja das Vorhandensein von EINEM ('position === position') oder KEINEM ('FALSE === FALSE') Punkt.
    Bei substr_count() müsstest du das Ergebnis auf Gleichheit mit 1 oder 0 prüfen. Das ginge in einem Rutsch mit 'substr_count() < 2', wenn sich substr_count() auf ewig an die Angaben im Handbuch hält, dass es INTeger zurückliefert, die größer oder gleich 0 sind.

    *nachtrag*
    Irgendwie bin ich heute zu langsam ... ;-)


    Original geschrieben von ghostgambler
    Nebenbei machen wir uns jetzt bewusst, dass diese Einschränkung für den vorliegenden Fall vollkommen irrelevant ist.
    Oder möchten Sie mir einen String kreieren, wo die eine Funktion einen Punkt an der ersten Stelle findet, die zweite Funktion dann jedoch keinen Punkt findet? Ich glaube ich vermag einwandfrei zu beweisen, dass es einen derartigen String nicht geben wird... entweder liefern beide Funktionen False, oder sie liefern beide einen numerischen Wert.
    Mach mal. ;-) Nein -- Sie[1] haben natürlich recht. Wenn (mindestens) ein Punkt vorhanden ist, dann sollten beide Funktionen kein FALSE liefern.

    Übrigens, Forenregeln!
    Die hier?
    Keine horizontalen Scrollbalken
    Informatiker sind FAUL! Folglich mag hier niemand eine horizontale Scrollbar nach rechts bewegen. Achtet also beim Posten darauf, dass ihr bei "breitem" Quelltext entsprechende Umbrüche in den Text einfügt, so dass euer Posting bei einer Auflösung von 1024 Pixeln (Breite) ohne Hindernisse zu lesen ist.


    Du bist also Informatiker? ;-)

    Dein Code sprengt meine Auflösung von >1024.
    Meine nicht (ebenfalls 1024 Pixel in der Waagerechten).
    Woher soll ich wissen, wann deine Auflösung gesprengt wird?
    Gibts die Angabe einer maximalen Zeichenzahl pro Zeile, oder kann ich die Überschreitung eines Zeilenbreiten-Limits irgendwie anders verifizieren?

    --
    [1] Reden wir uns heute mit Sie an?
    Zuletzt geändert von fireweasel; 02.01.2009, 12:22.
    Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

    Kommentar


    • #17
      80 Zeichen pro Zeile.

      Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

      bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
      Wie man Fragen richtig stellt

      Kommentar


      • #18
        Original geschrieben von fireweasel
        Du fragst 4 Bedingungen ab, die du über drei Zeilen verteilst, ich nur eine auf einer Zeile.
        Ich denke, die Menge an Quelltext ist nicht entscheident (auch nicht die Geschwindigkeit), sondern die Übersichtlichkeit.
        Dein Regex-Ungetüm ist mir jetzt schon zu unübersichtlich, geschweige denn, wenn Du es noch erweiterst.
        Da ist ghostgamblers Code schon bedeutend einfacher nachzuvollziehen bzw. zu erweitern. Nach dem Grundsatz "Teile und herrsche".

        Was nützt es mir, wenn ich alles in einen Regex gieße und nach drei Wochen, wenn ich die Stelle erweitern möchte erstmal eine halbe Stunde benötige mich da wieder reinzudenken?

        Kommentar


        • #19
          Ein "Ungetüm" ist das imho noch lange nicht. Darüber hinaus sollte die eingerückte und dokumentierte Darstellung selbstredend sein, so wie Code im Allgemeinen dokumentiert werden sollte, um auch nach längerer Zeit auf Anhieb nachvollziehbar zu sein. Dass die String-Funktionen leichter zu erweitern sind, halte ich für inkorrekt bis mindestens debattierbar.


          Grüße
          Nieder mit der Camel Case-Konvention

          Kommentar


          • #20
            Sooo, ich hab den RegEx nochmal überarbeitet und vereinfacht (oder verkürzt).
            Nebenbei funktioniert er jetzt auch. Bei der alten Variante, hat die Verankerung am Ende gefehlt, so dass auch Strings mit mehr als einem Punkt als passend erkannt wurden.

            Das Ganze wie oben in eigene Funktionen verpackt und die preg_match()-lose Variante zum Vergleich:
            PHP-Code:
            // Wichtig: man vergesse hierbei bitte nicht, 
            // dass die Boardsoftware Backslashes schluckt ;-)
            // Also Kopieren nur über die Zitat-Funktion.

            function regex_3(
              
            $txt
            ) {
              static 
            $pcre '/\A(?=[^\.]*(?:\.[^\.]*)?\z)[a-z0-9_\.]{4,10}\z/';
              
            // \A                # verankern am Anfang

              // (?=              # Lookahead-Assertion:
              // [^\.]*            # kein Punkt, keinmal oder beliebig oft

              // (?:              # diese Klammer nicht zwischenspeichern
              // \.[^\.]*           # ein Punkt, gefolgt von keinem 
                                  # oder beliebig vielen Punkten
              // )?               # das Ganze ist optional                       
              // \z)               # bis zum Ende des Strings

              // [a-z0-9_\.]{4,10} # 4--10 Zeichen
              //                  # erlaubt: a--z, 0--9, _, .
              // \z                # Verankern am Ende
              
            return (bool) preg_match($pcre$txt);
            }

            function 
            strlen_strpos_strspn(
              
            $txt
            ) {
              static 
            $dot '.';
              return
                  
            strlen($txt) >= && strlen($txt) <= 10 &&
                  
            strpos($txt$dot) === strrpos($txt$dot) &&
                  
            strspn($txt'abcdefghijklmnopqrstuvwxyz1234567890_.');

            Und das entsprechend geänderte Testskript:

            PHP-Code:
            $pcre '/\A(?=[^\.]*(?:\.[^\.]*)?\z)[a-z0-9_\.]{4,10}\z/';

            // test:
            $dot '.';
            // laengen von 3 bis 10 Zeichen
            for ($size 3$size <= 11; ++$size) {
              
            $base_haystack str_repeat('0'$size);
              
            // dot von position 0 bis letztmoegliche position
              // bei "position" -1 ohne punkt
              
            for ($dot_pos = -2$dot_pos strlen($base_haystack); ++$dot_pos) {
                
            $haystack $base_haystack;
                if (isset(
            $haystack[$dot_pos])) {
                  
            $haystack[$dot_pos] = $dot;
                }
                elseif (
            $dot_pos < -1) {
                  
            $haystack[0] = $dot;
                  
            $haystack[1] = $dot;
                }
                
            $should_match = (
                  
            strlen($txt) >= && strlen($txt) <= 10 &&
                  
            strpos($txt$dot) === strrpos($txt$dot) &&
                  
            strspn($txt'abcdefghijklmnopqrstuvwxyz1234567890_.');
                ) ? 
            0;

                
            $has_match preg_match($pcre$haystack);
                
            // fuer Testausgabe im Browser
                
            printf(
                    
            'len(%s) %s passt? %d richtig? %d<br />'
                    
            strlen($haystack), 
                    
            $haystack
                    
            $has_match
                    
            $has_match === $should_match
                
            );
              }

            Ich denke, die Menge an Quelltext ist nicht entscheident (auch nicht die Geschwindigkeit), sondern die Übersichtlichkeit.
            ... und die Beherrschung der deutschen Rechtschreibung? ;-)
            Nein, im Ernst: Natürlich ist ohne die genauere Kenntnis darüber, wie diese Prüfung eingesetzt werden soll, eine Diskussion über Geschwindigkeit oder Quelltextmenge eher theoretischer Natur. Ich habe so den vagen Verdacht, dass der OP lediglich die Angaben aus einem Web-Formular prüfen wollte. Dann wäre eine Optimierung auf Geschwindigkeit Zeitverschwendung. Aber auf größere Datenmengen angesetzt, kann ein Laufzeitunterschied von 30 Prozent schon einiges ausmachen. Und als (aller)letztes Wort dazu noch: Die Ausführungsgeschwindigkeit der PCRE-losen Variante hängt stark von der Reihenfolge der einzelnen Prüfschritte und der Beschaffenheit der zu prüfenden Zeichenkette ab.

            Dein Regex-Ungetüm ist mir jetzt schon zu unübersichtlich, ... geschweige denn, wenn Du es noch erweiterst.
            Hmmm, du hast anscheinend auch noch ein paar Semester Informatikstudium vor dir. ;-) Glaub mir einfach, du wirst irgendwann die Worte "Ungetüm", "unübersichtlich" und ähnliche nicht mehr im Zusammenhang mit so einem simplen PCRE verwenden.

            ... geschweige denn, wenn Du es noch erweiterst.
            Nun die "Erweiterung" um Großbuchstaben, auf die ich mich bezog, ist mit einem kleinen "i" am Ende des PCRE abgefrühstickt. Ähnliches gilt für Unicode-Kompatibilität (zumindest für UTF-8).
            Zuletzt geändert von fireweasel; 05.01.2009, 18:39.
            Klingon function calls do not have “parameters”‒they have “arguments”‒and they always win them!

            Kommentar

            Lädt...
            X