【发布时间】:2013-07-10 12:22:05
【问题描述】:
我一直在尝试使用正则表达式“解析”一些数据,我感觉好像很接近了,但我似乎无法将其全部带回家。
需要解析的数据一般是这样的:<param>: <value>\n。参数的数量可以变化,就像值一样。不过,这里有一个例子:
为了将这个文本推入一个对象,我把这个小表达式放在一起
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 可以为空)。在这种情况下,我的表达式不会失败,而是会导致:
我一直在尝试其他各种表达方式,并想出了这个:
/^([^:\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,}:)|.)*+)
至少在我看来,这太复杂了,不是唯一的选择。想法、建议、链接......任何东西都会非常感激
【问题讨论】:
-
如果内容也可能包含冒号,我们可以使用什么标准来识别它们,以免将它们与分隔键/值的冒号混淆?
-
@TimPietzcker:很好,我已经检查过了。该文本由另一个程序生成,该程序实际上在用户输入中转义了冒号。我已经在这里和我的代码中更新了我的表达方式:)
-
哦,如果冒号被转义,那就很容易了。等一下。
标签: php regex preg-match-all