1

编辑:

似乎人们认为我正在尝试解析 HTML,而我已经强调了几次我正在尝试解析日志,并且<option>结构类似于我的日志。

我的日志看起来像这样:

!# [2013-03-04 14:51:31] // cluster1 BEGIN \\ 
!## apache: 41
!## mysql: 31
!## tomcat: 81
!## lotus: 985
!# [2013-03-04 14:51:56] // cluster1 END \\ 
!# [2013-03-04 14:51:56] // cluster2 BEGIN \\ 
!## apache: 13
!## mysql: 61
!## tomcat: 6
!## lotus: 513
!# [2013-03-04 14:52:13] // cluster2 END \\ 

我不能让这个正则表达式工作,也许这是不可能的..需要帮助:)

基本上,我试图一次从父实体中对多个子元素进行正则表达式。为简洁起见,我将使用下拉<select>HTML 元素作为示例。这实际上将用于日志解析,但我还不确定它将是什么格式,并且下拉元素与我需要的一样接近,而无需解释日志的结构。

所以让我们假设我们有一个下拉列表:

<select class="parent">
    <option value="1">First child</option>
    <option value="2">Second child</option>
    <option value="3">Third child</option>
    ...
</select>

要将<option>元素与父元素分开,我会使用这个:

preg_match_all('/<select class="parent">(.*)<\/select>/is', $source, $matches);

这是伟大的。但是现在我必须花一点时间preg_match()来过滤掉我的<option>元素,所以它看起来像这样:

preg_match_all('/<option value="(.*?)" >(.*?)<\/option>/is', $matches['1'], $finalMatches);

我的结果很好。但是有没有办法将这两个命令组合成一个规则?所以它会找到父元素,在这种情况下是一个<select class="parent">*</select>块,并过滤掉在该父元素中找到的每个<option value="*">*</option>条目?然后我会留下一个完美的父子组合数组,而不是迭代第一个结果,然后让每次迭代完成另一个 preg_match 函数。

4

1 回答 1

2

我想这就是你要找的:

preg_match_all(
    '~(?:<select class="parent">|\G)\s*<option value="(.*?)">(.*?)</option>~i',
    $source, $matches);

\G将匹配锚定到前一个匹配结束的位置(如果没有前一个匹配,则锚定到输入的开头)。因此,第一个匹配项将包含开始<select>标记和第一个<option>元素,之后的每个匹配项都将包含下一个 <option>元素——它不会跳过在后面的<select>元素中查找匹配项。

这是一个演示。我还使用\K了 Match Start Reset 运算符,但这不是必需的;我只是认为它使输出更易于阅读。它有效地将之前的所有内容转变为积极的回顾,而没有通常的限制。

于 2013-03-05T14:11:49.687 回答