Ankündigung

Einklappen
Keine Ankündigung bisher.

preg_match_all läuft Amok

Einklappen

Neue Werbung 2019

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

  • preg_match_all läuft Amok

    Hallo,

    ich habe vor einiger Zeit ein kleines Tool gebastelt, dass es den Spielern eines Browser-Spiels ermöglichen soll, ein paar organisatorische Aufgaben u erledigen.

    Dazu wird der Inhalt einer Website manuell in ein textarea kopiert und dann ausgewertet.

    Bisher hat das mit Firefox und IE ganz gunt funktioniert.

    Nach dem Start einer neuen Runde des Spiels wurden scheinbar ein paar Ausgaben verändert und das Such-muster passt nicht mehr ganz genau.

    Interessant ist aber, was nun passiert. Statt einfach nichts zu finden, kehr preg_match_all scheinbar nicht mehr zurück und die Bearbeitng des Scripts wird abgebrochen.

    Hier mal die Nachrichten, die zu parsen sind:

    Alle Nachrichten vernichten: Nachricht verbrennen | Alle markierten Nachrichten löschen:



    Botschaft von: Eurer Handelsniederlassung
    Eines Eurer Handelsangebote wurde angenommen.
    Grimbart der Schlaechter bezahlte 200 Holz für 20 Gold.
    Wurde Euch überbracht am: 19. November 06 13:21
    Nachrichten
    Nachricht verbrennen Diese Nachricht archivieren


    Botschaft von: Eurer Handelsniederlassung
    Eines Eurer Handelsangebote wurde angenommen.
    Grimbart der Schlaechter bezahlte 150 Holz für 15 Gold.
    Wurde Euch überbracht am: 19. November 06 13:21
    Nachrichten
    Nachricht verbrennen Diese Nachricht archivieren
    Hier der relevante Teil des Scripts (gekürzt):

    PHP-Code:
    <?php
    echo "HALLO!!!!
    \n"
    // DAS sollte eigentlich immer ausgegeben werden!
    ...
        if (isset(
    $_POST['berichte']))
        {
            echo 
    'Eingegebene Berichte: 
    '
    .$_POST['berichte'].'
    '
    ;
            
            
    $Suchmuster1 '#' .
                    
    'Botschaft von: Eurer Handelsniederlassung (.|\n)+' .
                    
    '.*Wurde Euch überbracht am: \d+\. [^ ]+ \d+ \d+\:\d+ Uhr' .
                    
    '#U';
            
    preg_match_all($Suchmuster1$_POST['berichte'], $ErgebnisPREG_PATTERN_ORDER);
                    exit();
    ?>
    Egal, was preg_match_all so findet oder nicht, sollte oben HALLO ausgegeben werden. Außerdem sollte "Eingegebene Berichte: ..." erscheinen.

    Was statt dessen passiert ist folgendes:
    Im TaskManager sehe ich, dass nach Absenden des Formulars die CPU-Auslastung für einige Sekunden merklich ansteigt. Von 3%-4% auf 60%-70%. Danach fällt sie wieder ab auf den vorherigen Wert.

    In der Prozessansicht ist im gleichen Zeitraum ein Anstieg des Rechenzeitanteils des Apachen festzustellen.

    Irgendwas macht das Script also.

    Aber auch wenn wieder alles auf Ruheniveau ist, kommt keine Ausgabe im Browser heraus.

    Lasse ich den zweiten Teil der Eingabe weg, so wird zwar kein gültiger Bericht erkannt, aber immerhin erfolgen die Ausgaben wie erwartet.

    Alle Nachrichten vernichten: Nachricht verbrennen | Alle markierten Nachrichten löschen:



    Botschaft von: Eurer Handelsniederlassung
    Eines Eurer Handelsangebote wurde angenommen.
    Grimbart der Schlaechter bezahlte 200 Holz für 20 Gold.
    Wurde Euch überbracht am: 19. November 06 13:21
    Nachrichten
    Nachricht verbrennen Diese Nachricht archivieren
    Woran kann das liegen?

    Das exit() habe ich nur eingefügt, um den Fehler im preg_match_all zu lokalisieren.


    Bei einer ganz anderen Gelegenheit ist mir dieses Verhalten auch schon aufgefallen. Statt einfach nur nichts zu parsen, erfolgte keine Ausgabe des Scripts.

    Das Problem tritt sowohl lokal (PHP 5.1.4), als auch bei meinem Hoster (PHP 4.4.2) auf.

    Bei größeren Eingebamengen würde ich noch verstehen, dass die Suche etwas aufwändiger wird und evtl. Speicher in Anspruch nimmt. Aber bei den derart reduzierten Mengen sollte das doch kein Problem sein.

    Hat irgendwer Erfahrungen mit derart seltsamen Verhaltensweisen?

  • #2
    Deine Pattern ist mir eh eben schleierhaft ... wo kommt im Text "Uhr" vor, wenn es im Pattern steht ?
    Oder Beispiel fehlerhaft ?

    Kommentar


    • #3
      Was hat das Muster mit dem Problem zu tun?

      Wie gesagt, wurde der Text im Spiel geändert. Nun kommt 'Uhr' eben überhaupt nicht mehr vor. Früher kam hinter der Uhrzeit noch das Wörtchen 'Uhr'.

      Das hat aber ja alles nichts mit dem Problem zu tun, dass preg_match_all() statt einfach nööööö zu sagen, das Script abkratzen lässt.

      Mit dem oben genannten Muster suche ich aus dem Postfach des Spielers erstmal nur alle relevanten Handelsnachrichten heraus und werte die dann in einem zweiten Schritt noch genauer aus. Das ist hier aber nicht relevant.

      Die Frage ist ja nicht, warum er das Muster nicht findet, sondern warum überhaupt keine Ausgabe erfolgt.

      Kommentar


      • #4
        ich geh mal davon aus, daß error_reporting(E_ALL) nix vermeldet hat oder?

        Kommentar


        • #5
          Ich weiß es nicht so genau.

          Es kommen keinerlei Ausgaben im Browser an.
          Nicht einmal die, die ich extra mit echo eingefügt habe.
          Wenn error_reporting() mir irgendwas mitteilen wollte, dann ist das zwischen den echo-Ausgaben im Nirvana gelandet.

          Kommentar


          • #6
            Was hat das Muster mit dem Problem zu tun?
            Damit man z.B. das Problem überhaupt nachvollziehen kann ...

            Kommentar


            • #7
              Darf preg_match_all() etwa das Script zum Abbruch bringen, wenn das Suchmuster nicht gefunden wird?

              Das Muster ist bekannt. Und mit dem genannte Text sollte wie Du ja korrekt festgestellt hast, keine Übereinstimmung erkannt werden.
              Das geschieht aber üblicherweise durch den Rückgabewert FALSE und Nicht durch den Abbruch des Scripts.

              Kommentar


              • #8
                reporting -> nirvana: stimmt. mein fehler

                ich hoffe mal, die schließende } Klammer ist nur ein Posting-Problem und existiert in deinem Script noch. Die wurde bei mir nämlich angemeckert. Ansonsten funktionierts lokal bei mir (PHP 4.3.2).

                Kommentar


                • #9
                  Ups. Ja klar. Das Script geht noch weiter. Nur hab ich den Teil nach dem exit() weggelassen.

                  Ich versuche gerade, ein Script zu erstellen, wo die Eingabe im textarea gleich als Stringkonstante enthalten ist.

                  Damit das ganze dann 1:1 nachvollziehbar ist.

                  Kommentar


                  • #10
                    So... Um das leichter nachvollziehen zu können, habe ich das Script mal extrahiert:

                    PHP-Code:
                    <?php

                    $Suchmuster1 
                    '#' .
                        
                    'Botschaft von: Eurer Handelsniederlassung (.|\n)+' .
                        
                    '.*Wurde Euch überbracht am: \d+\. [^ ]+ \d+ \d+\:\d+ Uhr' .
                      
                    '#U';

                    $Bericht1 
                    "      Botschaft von: Eurer Handelsniederlassung      \r\n" .
                    "      Eines Eurer Handelsangebote wurde angenommen.\r\n" .
                    "Grimbart der Schlaechter bezahlte 200 Holz für 20 Gold.      \r\n" .
                    "      Wurde Euch überbracht am: 19. November 06 13:21      \r\n" .
                    "Nachrichten\r\n" .
                    "Nachricht verbrennen Diese Nachricht archivieren\r\n" .
                    "\r\n" .
                    "\r\n" .
                    "      Botschaft von: Eurer Handelsniederlassung      \r\n" .
                    "      Eines Eurer Handelsangebote wurde angenommen.\r\n" .
                    "Grimbart der Schlaechter bezahlte 150 Holz für 15 Gold.      \r\n" .
                    "      Wurde Euch überbracht am: 19. November 06 13:21      \r\n" .
                    "Nachrichten\r\n" .
                    "Nachricht verbrennen Diese Nachricht archivieren\r\n";

                    $Bericht2 
                    "  \tBotschaft von: Eurer Handelsniederlassung \t \r\n" .
                    "  \tEines Eurer Handelsangebote wurde angenommen.\r\n" .
                    "Grimbart der Schlaechter bezahlte 200 Holz für 20 Gold. \t \r\n" .
                    "  \tWurde Euch überbracht am: 19. November 06 13:21 \t \r\n" .
                    "Nachrichten\r\n" .
                    "Nachricht verbrennen Diese Nachricht archivieren\r\n" .
                    "\r\n" .
                    "\r\n" .
                    "  \tBotschaft von: Eurer Handelsniederlassung \t \r\n" .
                    "  \tEines Eurer Handelsangebote wurde angenommen.\r\n" .
                    "Grimbart der Schlaechter bezahlte 150 Holz für 15 Gold. \t \r\n" .
                    "  \tWurde Euch überbracht am: 19. November 06 13:21 \t \r\n" .
                    "Nachrichten\r\n" .
                    "Nachricht verbrennen Diese Nachricht archivieren\r\n";

                    $Bericht3 
                    "  \tBotschaft von: Eurer Handelsniederlassung \t \r\n" .
                    "  \tEines Eurer Handelsangebote wurde angenommen.\r\n" .
                    "Grimbart der Schlaechter bezahlte 200 Holz für 20 Gold. \t \r\n" .
                    "  \tWurde Euch überbracht am: 19. November 06 13:21 \t \r\n" .
                    "Nachrichten\r\n" .
                    "Nachricht verbrennen Diese Nachricht archivieren\r\n";


                    echo 
                    "Hallo vor preg_match_all()...
                    \n"
                    ;

                    $Found preg_match_all($Suchmuster1$Bericht2$ErgebnisPREG_PATTERN_ORDER);

                    echo 
                    "Found = $Found
                    \n"
                    ;
                    echo 
                    'Ergebnis: <pre>';
                    print_r($Ergebnis[0]);
                    echo 
                    '</pre>
                    '
                    ;

                    ?>
                    $Bericht1 und $Bericht2 unterscheiden sich nur dadurch, dass die Tabulatoren im ersten noch direkt enthalten sind und im zweiten durch \t ersetzt wurden.

                    Man kann beide in preg_match_all() einsetzen und erhält in beiden Fällen keine Ausgabe.

                    Setzt man jedoch $Bericht3 ein, so läuft das Script wie erwartet und gibt "Found = 0" aus.

                    Kommentar


                    • #11
                      Bei mir läuft auch das.

                      Kommentar


                      • #12
                        Du kriegst also jedesmal die Ausgabe Found = 0, wenn Du jeweils Bericht1, 2 oder 3 an die Funktion übergibst?

                        Kommentar


                        • #13
                          Na suuuper.
                          Ich hab es gerade nochmal auf meinem externen Server gepackt und da geht das Script jetzt.
                          Lokal mit XAMPPlite geht es nicht. Nur bei Bericht3 erfolgt eine Ausgabe.

                          Mir ist das Fehlverhalten aber derfinitiv zuerst auf dem externen Server aufgefallen. Erst danach habe ich lokal einige Tests durchgeführt.

                          Nur waren das andere Daten, die eingegeben wurden.
                          Offensichtlich hängt das Fehlverhalten von dem zu durchsuchenden Text ab.
                          Aber anscheinend ist das auch noch unterschiedlich bei meinen beiden Servern.


                          Ganz toll.
                          Ich kann zwar das Suchmuster an die neuen Texte anpassen, aber die Gefahr, dass bei einem beliebigen abweichenden Text einfach mal nix passiert gefällt mir gar nicht. Es sollen ja die passenden Nachrichten aus einer Vielzahl verschiedener Nachrichten herausgesucht werden. Es werden also evtl. mehr Texte durchsucht, die nicht zutreffen, als welche die zutreffen.
                          Das gefällt mir irgendwie gar nicht...

                          Kommentar


                          • #14
                            Darf man fragen, welches OS benutzt wurde ?

                            EDIT:

                            Hat sich erledigt.
                            XAMPP hängt sich hier auf:
                            Code:
                            (.|\n)+
                            Besser gesagt am . selber.

                            Kommentar


                            • #15
                              Bei meinem Hosting-Anbieter ist Linux im Einsatz.

                              Lokal habe ich WinXP und verwende XAMPP-LITE.

                              Aber mir ist zunächst auf dem externen Server aufgefallen, dass da was nicht stimmt. Und dann hab ich das lokal ausprobiert.
                              Ob das externe Problem auch dieses preg_mach_all-Verhalten war, kann ich nicht mit 100% Sicherheit sagen. Vielleicht lag es auch an was anderem. Im Moment ist das Problem weg.
                              Nur lokal macht das obige Test-Script Ärger.

                              Kommentar

                              Lädt...
                              X