2017-12-06 11 views
1

Ich habe dieses RegEx von meiner vorherigen Frage. Das Problem ist, dass es manchmal funktioniert, manchmal nicht. Ich versuchte es auf einem Online-Simulator einfügen und diese bekam: https://regex101.com/r/I3tnY4/3Literale Leerraumzeichen, die dazu führen, dass das Muster fehlschlägt (manchmal)

Der Text aus einer Datei, die ich

file_get_contents

Der Inhalt der Datei vollständig lesen verwenden, aber wenn ich laufe es durch die RegEx, um es zu filtern:

 $data = file_get_contents($var); 
     $pat = '/intervals \[\d+\]:\s+\Kxmin = (?P<xmin>\d+(\.\d+)?) \ 
       \s+xmax = (?P<xmax>\d+(\.\d+)?)\s+text = "(?P<text>[^"]*)"/m'; 

     // print_r($data); 
     preg_match_all($pat, $data, $m); 
     $result = array_map(function($a){ 
      return array_combine(['xmin', 'xmax', 'text'], $a); 
     }, array_map(null, $m['xmin'], $m['xmax'], $m['text'])); 

     print_r($result); 

es gibt ein leeres Array zurück. Am Anfang funktionierte es, aber als ich eine for-Schleife hinzufügte, um mehrere Dateien hochzuladen, funktionierte es nicht mehr.

Das ist auch schon passiert, als ich versucht habe, die Datei direkt nach dem Upload zu bearbeiten.

So:

if (move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], $target_file)) { 
     if (file_exists($target_file)) { 
      $data = file_get_contents($target_file); 
      $pat = '/intervals \[\d+\]:\s+\Kxmin = (?P<xmin>\d+(\.\d+)?) \ 
      \s+xmax = (?P<xmax>\d+(\.\d+)?)\s+text = "(?P<text>[^"]*)"/m'; 


      preg_match_all($pat, $data, $m); 
      $result = array_map(function($a){ 
       return array_combine(['xmin', 'xmax', 'text'], $a); 
      }, array_map(null, $m['xmin'], $m['xmax'], $m['text'])); 

      print_r($result); 
     } 
    } 

Mit dem obigen Code, der RegEx auch nicht, da das $ result Array leer war. Ich vermutete, dass die Datei noch nicht bereit war, gelesen zu werden oder so. Auch wenn ich den Inhalt der Datei ausgedruckt habe, war alles da. Was ich also gemacht habe, war, meine Seite in eine andere Datei umzuleiten, die die RegEx-Verarbeitung durchgeführt hat, und überraschenderweise hat es dort funktioniert.

+0

Kommentar für den Downvote, bitte. Dies ist eine sehr detaillierte Frage, die von jemandem kommt, der RegEx nicht so gut beherrscht wie Sie. – hungrykoala

+1

Ich habe nicht heruntergestimmt, aber ich wollte den Titel der Frage sehen. Bitte verwenden Sie * aussagekräftige * Titel. –

+0

@ WiktorStribiżew Ich hatte es eilig und konnte mir nichts Besseres einfallen lassen. Obwohl das Beste, was ich mir jetzt vorstellen kann, ungefähr so ​​ist: "Regex scheitert an preg_match_all beim Lesen von Inhalten aus der Datei mit file_get_contents" – hungrykoala

Antwort

1

Es scheint, dass Ihre Aufgabe eher auf die Extraktion von Teilstrings als auf die Validierung ausgerichtet ist. Aus diesem Grund können Sie weitgehend die Größe des Musters verringern, beschleunigen die Ausführung und die Ausgabe aufblasen mit dem folgenden Muster minimieren:

/xmin = (\S+)\s+xmax = (\S+)\s+text = "([^"]*)/ 

Was habe ich getan? (Siehe this demo für die amtlichen Muster Aufschlüsselung)

  • Entfernen Sie den führenden interval... Matching, da Sie nicht verwenden (oder genauer gesagt die Zahl innerhalb von []:
  • \K entfernen, weil Sie nicht auf „Neustart“ müssen die fullstring match - Sie verwenden es nicht
  • Entfernen Sie die benannten Erfassungsgruppen, da Sie array_map() und array_combine() verwenden, um diese Schlüsselnamen irgendwie zuzuordnen. Named Capture-Gruppen verursachen Hauptausgabe Array Bloat und sollte vermieden werden, es sei denn, Sie haben Zwingender Grund, sie zu verwenden. Der Grund, den sie verursachen Das Problem besteht darin, dass preg_match_all(), wenn Sie Capture-Gruppen benennen, doppelte Subarray-Elemente (das benannte und das indizierte) schreiben - dies bedeutet doppelte Datenmenge. Ja, Sie können zwar benannte Erfassungsgruppen verwenden, dies würde jedoch nur bedeuten, dass Sie Ihren -Prozess ändern würden, um alle indizierten Elemente aus jedem Unterfeld zu entfernen ([0],[1],[2],[3]).
  • Entfernen Sie die Unterbrechung in Ihrem Muster.Wenn Sie ein oder mehrere Leerzeichen einfügen möchten (in Ihrem Fall Zeilenumbrüche, Leerzeichen und möglicherweise Tabulatoren), verwenden Sie einfach \s+. Für den Rekord können Sie whitespaces in Ihrem Muster verwenden, um Lesbarkeit zu verbessern, aber dazu müssen Sie x als eine Markierung am Ende Ihres Musters einschließen. Der x Mustermodifikator ignoriert alle im Muster verwendeten Leerzeichen, also hüte dich vor diesem Effekt.
  • Ersetzen Sie (?P<xmax>\d+(\.\d+)?) durch (\S+). Dadurch werden die benannte Erfassungsgruppe und die verschachtelte Erfassungsgruppe entfernt und die gesamte Nicht-Whitespace-Teilzeichenkette extrahiert. Wenn Sie diese Zeichenfolge validieren möchten, rate ich: (\d+(?:\.\d+)?) Dies ändert die verschachtelte Gruppe in "non-Capturing" - wieder Ausgabe Array Bloat reduziert.
  • Sie waren klug, eine negierte Capture-Gruppe für die letzte Capture-Gruppe zu verwenden. Dies ist der effizienteste Weg, um sie zu erreichen. Sie brauchen den nachlaufenden " nicht, damit dieser entfernt werden kann.
  • Entfernen Sie den m Mustermodifikator. Sie verwenden keine Anker-Metazeichen (^ oder $), so dass die Flagge keinen Zweck hat.
  • preg_match_all() Der vierte Parameter PREG_SET_ORDER strukturiert Ihre Subarrays so, dass nur ein array_map() erforderlich ist, um Ihr mehrdimensionales Array einzurichten.

Dies ist, wie ich, dass Sie es implementieren vorschlagen:

Code: (Demo)

$data='intervals [1]: 
    xmin = 0 
    xmax = 13.139997023062838 
    text = "" 
intervals [2]: 
    xmin = 13.139997023062838 
    xmax = 14.763036269953904 
    text = "Cities are like siblings in a large polygamous family." 
intervals [3]: 
    xmin = 14.763036269953904 
    xmax = 17.01 
    text = ""'; 
$pat='/xmin = (\S+)\s+xmax = (\S+)\s+text = "([^"]*)/'; 
if(preg_match_all($pat,$data,$m,PREG_SET_ORDER)){ 
    $assoc_multidim=array_map(function($a){return array_combine(['xmin','xmax','text'],array_slice($a,1));},$m); 
    var_export($assoc_multidim); 
}else{ 
    echo "substring extraction failed"; 
} 

Ausgang:

array (
    0 => 
    array (
    'xmin' => '0', 
    'xmax' => '13.139997023062838', 
    'text' => '', 
), 
    1 => 
    array (
    'xmin' => '13.139997023062838', 
    'xmax' => '14.763036269953904', 
    'text' => 'Cities are like siblings in a large polygamous family.', 
), 
    2 => 
    array (
    'xmin' => '14.763036269953904', 
    'xmax' => '17.01', 
    'text' => '', 
), 
) 


Eine alternative Methode, die Verwendung Ihrer benannten Capture-Gruppen macht würde wie folgt aussehen: (Demo)

$pat='/xmin = (?P<xmin>\S+)\s+xmax = (?P<xmax>\S+)\s+text = "(?P<text>[^"]*)/'; 
if(preg_match_all($pat,$data,$m,PREG_SET_ORDER)){ 
    $assoc_multidim=array_map(function($a){return array_intersect_key($a,['xmin'=>'','xmax'=>'','text'=>'']);},$m); 
    var_export($assoc_multidim); 
}else{ 
    echo "substring extraction failed"; 
} 

... Sie sehen, beide Techniken ein wenig aufzuräumen erfordern (es sei denn, Ihre Prozesse don zu folgen‘ (Beachten Sie die indizierten Subarrays), deshalb bevorzuge ich das weniger aufgeblähte Array.

+0

Es ist wirklich kleiner. Aber können Sie ein Beispiel für die Verwendung von Leerzeichen mit 'x' Parameter zeigen? – hungrykoala

+0

Sehen Sie, was ich mit meinem Telefon finden kann ... https://stackoverflow.com/questions/2710387/php-clean-up-regex und https: // stackoverflow.com/questions/22552/passing-a-commented-multi-line-freespace-regex-zu-preg-match und https://stackoverflow.com/questions/7512781/php-regexp-how-to-use-newline- In-Ausdruck und https://Stackoverflow.com/a/45400694/2943403 – mickmackusa

+0

danke für das – hungrykoala

1

Versuchen Sie, die folgende regex statt (DEMO, PHP Demo):

/(intervals \[\d+\]:)\s+\Kxmin = (?P<xmin>\d+(\.\d+)?)\s+xmax = (?P<xmax>\d+(\.\d+)?)\s+text = "(?P<text>[^"]*)"/m 

Es gibt keine Notwendigkeit, alle den zusätzlichen Platz zu setzen, wie \s+ alles abdecken wird.

+0

Was meinst du mit extra Raum? – hungrykoala

+0

Die Newline, ich meinte, in der Regex. – mega6382

+0

Also, hat es funktioniert? – mega6382

Verwandte Themen