2016-04-03 17 views
1

Ich habe einen regulären Ausdruck geschrieben, den ich in rugular.com getestet und es gab 4 Übereinstimmungen zurück. Das Thema der Prüfung kann hier http://pastebin.com/49ERrzJN gefunden werden und der PHP-Code ist unten. Aus irgendeinem Grund gibt der PHP-Code nur die ersten 2 Übereinstimmungen zurück. Wie man es macht, um alle 4 zusammenzubringen? Es scheint, dass es etwas mit Gier oder so zu tun hat.PHP preg_match_all Problem

$file = file_get_contents('x.txt'); 
preg_match_all('~[0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})~', $file, $m, PREG_SET_ORDER); 
foreach($m as $v) echo 'S: '. $v[1]. '; N: '. $v[3]. '; D:'. $v[7]. '<br>'; 
+2

Was genau möchten Sie extrahieren? – Druzion

+0

Ist nicht rubular.com für ** Ruby **? – Laurel

+0

@Druzion: Name, Nachname, DOB, Sex vor allem – pedmillon

Antwort

2

Ihre regex ist sehr slooooooow. Nachdem ich es auf regex101.com ausprobiert habe, habe ich festgestellt, dass es bei PHP (außer JS, aus welchem ​​Grund auch immer) ein Timeout geben würde. Ich bin mir ziemlich sicher, dass die Zeitüberschreitung bei etwa 50.000 Schritten passiert. Eigentlich macht es jetzt Sinn, warum Sie keinen Online-PHP-Regex-Tester verwenden.

Ich bin nicht sicher, ob dies die Ursache des Problems ist, sondern there is a default memory limit in PHP:

memory_limit [Standard:] "128M"

[Geschichte:] "8M" vor PHP 5.2.0 „16M“ in PHP 5.2.0

Wenn Sie die m ultiline Modifikator (ich gehe davon aus, dass preg_match_all im wesentlichen des Modifikator g lobaler hinzufügt), können Sie diese Regex verwenden, die nur 1282 Schritte zu fi nehmen nd alle 4 Treffer:

^ [0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})

Tatsächlich gibt es nur zwei Zeichen, die ich hinzugefügt. Sie sind am Anfang, der Anker ^ und der Literalraum.

+0

danke, die 2 Zeichen und die Verwendung von m Modifikator tat den Job – pedmillon

+0

Patterns Probleme haben nichts mit PHP-Speicher zu tun. –

1

Wenn Sie ein langes Muster schreiben müssen, müssen Sie es zuerst lesbar machen. Verwenden Sie dazu den ausführlichen Modus (x Modifikator), der Kommentare und freien Abstand zulässt und benannte Captures verwendet.

Dann müssen Sie eine genaue Beschreibung von dem, was Sie suchen:

  • Ihr Ziel nimmt eine ganze Zeile => verwenden die Anker ^ und $ mit dem Modifizierungs m, und verwenden Sie die \h Klasse (das nur horizontale Leerstellen enthält) anstelle der \s Klasse.
  • anstelle dieser Art von ineffizienten Sub-Muster (?:(?!.....).){m,n} zu beschreiben, was Ihr Feld nicht enthalten, beschreiben Sie, was das Feld enthalten kann.
  • Verwenden Sie Atomgruppen (?>...) bei Bedarf anstelle von nicht einfangenden Gruppen, um nutzlose Rückverfolgung zu vermeiden.
  • in der Regel unter Verwendung von präzisen Zeichen Klassen vermeidet viele Probleme

Muster:

~ 
^ \h*+ # start of the line 
# named captures       # field separators 
(?<VOTERNO>  [0-9]+     ) \h+ 
(?<SURNAME>  \S+ (?>\h\S+)*?   ) \h{2,} 
(?<OTHERNAMES> \S+ (?>\h\S+)*?   ) \h{2,} 
(?<DOB>   [0-9]{2}-[0-9]{2}-[0-9]{4}) \h+ 
(?<SEX>   [FM]      ) \h+ 
(?<APPID_RECNO> [0-9A-Z/]+    ) \h+ 
(?<VILLAGE>  \S+ (?>\h\S+)*   ) 
\h* $ # end of the line 
~mx 

demo

Wenn Sie wissen wollen, was mit einem Muster schief geht, können Sie die Funktion preg_last_error()