我一直在尝试使用正则表达式“解析”一些数据,我感觉好像我很接近了,但我似乎无法把它全部带回家。
需要解析的数据一般是这样的:<param>: <value>\n
. 参数的数量可以变化,就像值一样。不过,这里有一个例子:
FooID:123456 姓名:查克 时间:2013 年 1 月 2 日 01:23:45 内部编号:789654 用户留言:您好, 这是可空的,但可以很长。文本可以分布在多行 并且可以以任意数量的 \n 开头。它也可以是空的。 更糟糕的是,这个 CAN 包含冒号(但它们是_“转义”_ 使用 `\`),甚至是基本标记!
为了将这个文本推入一个对象,我把这个小表达式放在一起
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
bit:.
不匹配新行,因为如果我要使用s
标志,第二组将匹配FooID:
字符串末尾之后的所有内容。
我不得不为此使用肮脏的解决方法:
$msg = explode(end($data[1], $string);
$data[2][count($data[2])-1] = array_pop($msg);
经过一些测试,我开始明白有时,一两个参数没有填写(例如InternalID
可以为空)。在这种情况下,我的表达式不会失败,而是会导致:
[1] => 数组 ( [0] => FooID [1] => 名称 [2] => 什么时候 [3] => 内部 ID ) [2] => 数组 ( [0] => 123465 [1] => 查克 [2] => 2013 年 1 月 2 日 01:23:45 [3] => 用户评论:您好, )
我一直在尝试其他各种表达方式,并想出了这个:
/^([^:\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,}:)|.)*+)
至少在我看来,这太复杂了,不能成为唯一的选择。想法,建议,链接,......任何东西都将不胜感激