Я пытался "разобрать" некоторые данные, используя регулярное выражение, и мне кажется, что я близок к этому, но я просто не могу собрать все это домой.
данные, требующие разбора, обычно выглядят так: <param>: <value>\n
. Количество параметров может варьироваться, как и значение. Тем не менее, вот пример:
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!
Чтобы вставить этот текст в объект, я составил это небольшое выражение
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);
}
Теперь это работает нормально большую часть времени, за исключением бита User Message
: .
не соответствует новым строкам, потому что, если бы я использовал флаг s
, вторая группа соответствовала бы всему после FooID:
до самого конца строки.
Мне приходится использовать грязный обходной путь для этого:
$msg = explode(end($data[1], $string);
$data[2][count($data[2])-1] = array_pop($msg);
После некоторого тестирования я понял, что иногда один или два параметра не заполнены (например, InternalID
может быть пустым). В этом случае мое выражение не терпит неудачу, а скорее приводит к:
[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, )
Я пробовал различные другие выражения и придумал это:
/^([^:\n\\]++)\s{0,}:(.*+)(?!^[^:\n\\]++\s{0,}:)/m
//or:
/^([^:\n\\]+)\s{0,}:(.*)(?!^[^:\\\n]+\s{0,}:)/m
Вторая версия немного медленнее.
Это решает проблемы, которые у меня были с InternalID: <void>
, но все же оставляет последнее препятствие: User Message: <multi-line>
. Использование флага s
не работает с моим выражением ATM.
Я могу думать только об этом:
^([^:\n\\]++)\s{0,}:((\n(?![^\n:\\]++\s{0,}:)|.)*+)
Что, по крайней мере, на мой взгляд, слишком сложно, чтобы быть единственным вариантом. Идеи, предложения, ссылки, ... все будет очень признательно