Ich habe eine Zeichenfolge, deren korrekte Syntax die Regex ^([0-9]+[abc])+$
ist. Beispiele für gültige Strings wären: '1a2b' oder '00333b1119a555a0c'
Der Übersichtlichkeit halber ist der String eine Liste von Paaren (Wert, Buchstabe) und die Reihenfolge ist wichtig. Ich bin mit der Eingabe-Zeichenfolge fest, so dass ich das nicht ändern kann. Während das Testen auf korrekte Syntax im Prinzip mit der obigen Regex einfach zu sein scheint, versuche ich mir die effizienteste Möglichkeit in PHP vorzustellen, eine konforme Zeichenkette in ein brauchbares Array umzuwandeln, etwa so:
Eingabe:
%Vor%Ausgabe:
%Vor%Ich habe Probleme mit preg_match. Zum Beispiel gibt dies nicht das erwartete Ergebnis, die Absicht ist greedy-Match auf EITHER \ d + (und speichern Sie das) oder [abc] (und speichern Sie diese), wiederholt bis Ende der Zeichenfolge erreicht.
%Vor%Das hat auch nicht funktioniert, die Absicht hier ist, gierige Übereinstimmung auf \ d + [abc] zu finden (und diese zu speichern), wiederholt bis das Ende der Zeichenfolge erreicht ist, und sie danach in Zahlen und Buchstaben aufzuteilen.
%Vor% Ich hatte geplant, die Syntax als Teil von preg_match zu prüfen, dann benutze die preg_match-Ausgabe, um die 'Blöcke' gierig anzupassen (oder die Trennzeichen beizubehalten, wenn preg_split benutzt wird), dann wiederhole bei Bedarf die Elemente von result 2 Zeit mit for (...; i+=2)
, um den Wert-Buchstaben in ihren Paaren zu extrahieren.
Aber ich kann nicht scheinen, dass diese einfache Methode preg_split () oder preg_match () reibungslos funktioniert, geschweige denn, ob es einen "sauberen" oder effizienteren Weg gibt.
Alle oben genannten Arbeiten. Aber sie schienen nicht die Eleganz zu haben, die ich wollte - sie mussten eine Schleife bilden, Array-Mapping verwenden oder (für preg_match_all ()) benötigten sie eine andere, fast identische Regex, nur um zu überprüfen, ob die Zeichenfolge der Regex entsprach.
Ich fand schließlich, dass preg_match_all () kombiniert mit named Captures es für mich gelöst hat. Ich hatte zuvor keine Captures für diesen Zweck verwendet und es sieht sehr kraftvoll aus.
Ich habe auch einen optionalen zusätzlichen Schritt hinzugefügt, um die Ausgabe zu vereinfachen, wenn Duplikate nicht erwartet werden (was nicht in Frage war, aber jemandem helfen könnte).
%Vor%Komplette Version mit Eingabe + Duplikatprüfung
%Vor%Erläuterung:
Dies verwendet preg_match_all () wie von @RomanPerekrest und @exussum vorgeschlagen, um die einzelnen Gruppen auszubrechen und die Zahlen und Buchstaben zu teilen. Ich habe benannte Gruppen verwendet, so dass das resultierende Array von $ raw_matches bereits mit den korrekten Namen erstellt wurde.
Aber wenn Duples nicht erwartet werden, dann habe ich einen zusätzlichen Schritt mit array_column () verwendet, der direkt Daten aus einem verschachtelten Array von Einträgen extrahiert und ein gewünschtes flaches Array erstellt, ohne Schleifen, Mapping, Walking oder Element zuweisen zu müssen nach Artikel: von
%Vor%zum "flachen" Array:
%Vor%Wenn benannte Regex-Matches zu weit fortgeschritten sind, dann können sie ignoriert werden - die Matches werden sowieso Nummern erhalten und das wird genauso gut funktionieren, Sie müssten Buchstaben manuell zuweisen und es ist nur schwerer zu folgen.
%Vor%Wenn Sie nach doppelten Buchstaben suchen müssen (was nicht in der Frage enthalten war, aber nützlich sein könnte), gehen Sie wie folgt vor: Wenn die ursprünglichen Übereinstimmungen & gt; 1 Einträge für jeden Buchstaben enthielten, dann wird dieser Buchstabe zu array_column () ein Schlüssel für das neue Array und doppelte Schlüssel können nicht existieren. Es wird nur ein Eintrag für jeden Buchstaben gespeichert. Also testen wir einfach, ob die Anzahl der gefundenen Übereinstimmungen mit der Anzahl der Übereinstimmungen im letzten Array nach array_coulmn übereinstimmt. Wenn nicht, gab es Duplikate.
Ihre Regex benötigt einige übereinstimmende Gruppen
%Vor%Dies bedeutet, dass alle Zahlen in einer Gruppe und alle Buchstaben in einer anderen übereinstimmen. Preg match all erhält alle Übereinstimmungen.
Der Schlüssel zur Regex ist das nicht gierige Flag ?
, das mit der kürzest möglichen Zeichenfolge übereinstimmt.
match[0]
ist die gesamte Übereinstimmung
match[1]
ist die erste Vergleichsgruppe (die Zahlen)
match[2]
ist die zweite Vergleichsgruppe (der Buchstabe)
Beispiel unten
%Vor%Ausgabe
%Vor% Einfache Lösung mit preg_match_all
(mit PREG_SET_ORDER
Flag) und array_map
Funktionen:
Die Ausgabe:
%Vor%Tags und Links php regex tokenize regex-greedy