匹配单个正则表达式中的多个匹配项

时间:2014-06-09 19:35:14

标签: php regex

我有一个看起来像

的字符串
$html = <<<EOT
<p><b>There are currently five entries in the London Borough of Barking &amp; Dagenham (LBBD):</b></p>
<p>My string 1<br>
My another string<br>
And this is also my string<br></p>
<p><i>Some text over here</i></p>
EOT;

我正在尝试提取&#34;我的字符串1&#34;,&#34;我的另一个字符串&#34;还有&#34;这也是我的字符串&#34;使用php preg_match 到目前为止我所拥有的是

preg_match("/There are currently .+ entries in .+:<\/b><\/p>\n<p>(.+<br>)\n+/", $html, $matches);
print_r($matches);

但它只返回原始字符串和第一次出现。有没有办法在字符串中返回一系列匹配的匹配项?感谢

3 个答案:

答案 0 :(得分:0)

使用preg_match_all()。与大多数语言一样,PHP不会将g修饰符包含在全局匹配(或替换)中。相反,您需要使用preg_match()preg_match_all(),或在使用preg_replace()时指定$limit(以使其不是全局的)。


默认情况下,preg_match_all()会使用标记$matchesPREG_PATTERN ORDER数组进行排序。换句话说:$matches[0]将是完整匹配的数组,$matches[1]将是捕获组1的数组。这意味着count($matches) !== $number_of_matches。如果您希望$matches[0]成为第一个匹配项及其捕获组的数组,请使用标记PREG_SET_ORDER

preg_match(
    "/There are currently .+ entries in .+:<\/b><\/p>\n<p>(.+<br>)\n+/",
    $html,
    $matches,
    PREG_SET_ORDER
);

答案 1 :(得分:0)

&#34;有没有办法在字符串中返回一系列匹配的匹配项?&#34; 是的,功能是preg_match_all()

现在,假设你真的只想要文本,而不是任何html元素,你可以使用它......

preg_match_all("/(<p>)?(.+)<br>/", $html, $matches);

然后,您想要在$matches[2]中查找所需的数组。这是因为所有匹配都存储在$matches[0]中,第一个分组存储在$matches[1]中(即抓取<p>标记),然后是您的内容在$matches[2](第二组)中捕获。如果有更多分组,他们会遵循相同的模式。

DEMO

话虽这么说,你应该考虑使用DOM解析器来做这样的事情,因为正则表达式通常在解析HTML时非常糟糕。

答案 2 :(得分:0)

您需要两个入口点,第一个是句子"There are currently...",直到开始<p>标记,第二个入点在<br>标记后面的最后一个匹配结束时开始\n换行符。

第一个结果将使用第一个入口点,下一个结果将使用第二个入口点。

\G是匹配先前匹配结束位置的锚点。此功能很有趣,因为preg_match_all重试匹配模式直到字符串结束。但是由于\G在开始时用字符串的开头初始化,我们需要避免这种情况添加(?!\A) (不在字符串的开头)

我使用.+来避免使用[^<]+,而不是使用\Q

为了更具可读性,我使用了详细模式(x修饰符),它允许忽略空格并在模式中添加注释。当我需要写文字空格时,我将它们放在\E\Q之间。 \E$pattern = <<<'EOD' ~ # using this delimiter instead of / avoids to escape all # the slashes (?: # first entry point \QThere are currently \E [^<]+? \Q entries in \E [^<]+ </b> </p> \n <p> | # second entry point (?!\A)\G <br>\n ) \K # removes all that have been matched before from match result [^<]+ # the string you want ~x EOD; if (preg_match_all($pattern, $text, $matches)) var_dump($matches[0]); 之间的所有字符都被视为文字(模式分隔符除外),并保留空格。

{{1}}