1

我想在<p>和之间捕获最多四组文本</p>。我可以使用以下正则表达式来做到这一点: <h5>Trivia<\/h5><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p>

要匹配的文本:

<h5>Trivia</h5><p>Was discovered by a freelance photographer while sunbathing on Bournemouth Beach in August 2003.</p><p>Supports Southampton FC.</p><p>She has 11 GCSEs and 2 'A' Levels.</p><p>Listens to soul, R&amp;B, <a href="/name/nm0005567/">Stevie Wonder</a>, <a href="/name/nm0291349/">Aretha Franklin</a>, <a href="/name/nm0713378/">Usher Raymond</a>, <a href="/name/nm0001391/">Michael Jackson</a> and <a href="/name/nm0584117/">George Michael</a>.</p>

它输出四行文本。如果有更多琐事项目或 <p>事件,它也可以按预期工作。

但如果琐事项目或组少于 4 个<p>,则它不会输出任何内容,因为它找不到第四组。如何使该组可选?

我试过了:<h5>Trivia<\/h5><p>(.*?)<\/p>(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?根据http://gskinner.com/RegExr/可以工作,但如果我把它放在 PHP 代码中它就行不通。它只检测一个组并将所有内容放入其中。

4

2 回答 2

1

您可以使用问号将每个选项设为<p>...</p>可选:

$pattern = '~<h5>Trivia</h5>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?~';

使用 Dom 也是一个不错的选择。

于 2013-04-30T22:56:58.940 回答
1

神奇的词是“转义”或“分隔符”,请继续阅读。

第一个正则表达式:之所以有效,是因为您将标签
<h5>Trivia<\/h5><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p>
中的字符转义为./</h5><\/h5>

但是在您的第二个正则表达式中(正确地将每个段落包含在一个可选的非捕获组中,获取 1 到 5 个段落):
<h5>Trivia</h5><p>(.*?)</p>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?
您忘记转义这些/字符。
那么它应该是:
$pattern = '/<h5>Trivia<\/h5><p>(.*?)<\/p>(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?/';

以上假设您将正则表达式放在两个/“分隔符”字符之间(出于传统习惯)。

为了更深入地研究兔子洞,应该注意,在 php 中,正则表达式的第一个和最后一个字符通常是一个“分隔符”,因此可以在末尾添加修饰符(如不区分大小写等)。

因此,您也可以使用~字符(或#等)作为分隔符,而不是转义您的正则表达式。
因此,您也可以使用您发布并附上的相同(第二个)正则表达式,例如:
$pattern = '~<h5>Trivia</h5><p>(.*?)</p>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?~';

这是一个有效的(基于网络的)示例#用作分隔符(只是因为我们可以)。

于 2013-05-01T00:06:32.563 回答