Regex mit möglichen leeren Übereinstimmungen und mehrzeiligen Übereinstimmungen
Ich habe es versucht"analysieren" Einige Daten verwenden einen regulären Ausdruck, und ich habe das Gefühl, dass ich nah dran bin, aber ich kann einfach nicht alles nach Hause bringen.
Die zu analysierenden Daten sehen im Allgemeinen folgendermaßen aus:<param>: <value>\n
. Die Anzahl der Parameter kann variieren, genau wie der Wert. Hier noch ein Beispiel:
FooID: 123456 Name: Chuck When: 01/02/2013 01:23:45 InternalID: 789654 User Message: Hello, this is nillable, but can be quite long. Text can be spread out over many lines And can start with any number of \n's. It can be empty, too. What's worse, though is that this CAN contain colons (but they're _"escaped"_ using `\`), and even basic markup!
Um diesen Text in ein Objekt zu schieben, habe ich diesen kleinen Ausdruck zusammengestellt
if (preg_match_all('/^([^:\n\\]+):\s*(.+)/m', $this->structuredMessage, $data))
{
$data = array_combine($data[1], $data[2]);
//$data is assoc array FooID => 123456, Name => Chuck, ...
$report = new Report($data);
}
Nun, das funktioniert die meiste Zeit in Ordnung, mit Ausnahme derUser Message
bisschen:.
stimmt nicht mit neuen Zeilen überein, denn wenn ich die verwenden würdes
Flagge, würde die zweite Gruppe alles danach passenFooID:
bis zum Ende der Saite.
Dafür muss ich eine schmutzige Problemumgehung verwenden:
$msg = explode(end($data[1], $string);
$data[2][count($data[2])-1] = array_pop($msg);
Nach einigen Tests habe ich festgestellt, dass manchmal ein oder zwei der Parameter nicht ausgefüllt sind (zum Beispiel derInternalID
kann leer sein). In diesem Fall scheitert mein Ausdruck nicht, sondern führt zu:
[1] => Array ( [0] => FooID [1] => Name [2] => When [3] => InternalID ) [2] => Array ( [0] => 123465 [1] => Chuck [2] => 01/02/2013 01:23:45 [3] => User Comment: Hello, )
Ich habe verschiedene andere Ausdrücke ausprobiert und mir Folgendes ausgedacht:
/^([^:\n\\]++)\s{0,}:(.*+)(?!^[^:\n\\]++\s{0,}:)/m
//or:
/^([^:\n\\]+)\s{0,}:(.*)(?!^[^:\\\n]+\s{0,}:)/m
Die zweite Version ist etwas langsamer.
Das löst die Probleme, mit denen ich hatteInternalID: <void>
, lässt mich aber dennoch mit dem letzten Hindernis zurück:User Message: <multi-line>
. Verwendung ders
flag macht mit meinem Ausdruck ATM nicht den Trick.
Daran kann ich nur denken:
^([^:\n\\]++)\s{0,}:((\n(?![^\n:\\]++\s{0,}:)|.)*+)
Was meiner Meinung nach zu komplex ist, um die einzige Option zu sein. Ideen, Vorschläge, Links, ... alles wäre sehr dankbar