一个更好的问题标题可能是:“匹配包含特定子字符串的DIV 元素。” 首先必须说正则表达式不是这项工作的最佳工具。最好使用 HTML 解析器来解析标记,然后在每个 DIV 元素的内容中搜索所需的子字符串。也就是说,由于您不想了解更多关于如何使用正则表达式来匹配非其他内容的信息,因此以下描述了使用正则表达式执行此操作的有限方法。
正如 Dogbert 正确指出的那样,这个问题确实与 Regular expression to match string not containing a word? 重复。但是,我看到您已经查看了该问题,但需要知道如何将此技术应用于子模式。
要匹配不包含特定单词(或单词)的字符串(子模式)的一部分,您需要在每个字符之前应用否定的前瞻断言检查。以下是您将如何处理打开和关闭 DIV 标记之间的文本。请注意,当仅使用单个正则表达式时,因为 DIV 元素可能是嵌套的,所以只有在嵌套的 DIV 元素的“最里面”找到 "HELLO" 才合理。
伪代码:
- 匹配开头的
DIV标签。
- 延迟匹配零个或多个字符,每个字符都不是
<div 或</div 的开头。
- 找到所需的字符串:
"HELLO" 后,继续匹配它。
- 继续(贪婪地)匹配零个或多个字符,每个字符都不是
<div 或</div 的开头。
- 匹配结束
</div>标签。
请注意,要仅匹配“最里面”的DIV 内容,必须在一次扫描元素内容时排除<DIV 和</DIV 一个字符。以下是经过测试的 PHP 函数形式的相应正则表达式:
// Find an innermost DIV element containing the string "HELLO".
function p1($text) {
$re = '% # Match innermost DIV element containing "HELLO"
<div[^>]*> # DIV element start tag.
(?: # Group to match contents up to "HELLO".
(?!</?div\b) # Assert this char is not start of DIV tag.
. # Safe to match this non-DIV-tag char.
)*? # Lazily match contents one chara at a time.
\bhello\b # Match target "HELLO" word inside DIV.
(?: # Group to match content following "HELLO".
(?!</?div\b) # Assert this char is not start of DIV tag.
. # Safe to match this non-DIV-tag char.
)* # Greedily match contents one chara at a time.
</div> # DIV element end tag.
%six';
if (preg_match($re, $text, $matches)) {
// Match found.
return $matches[0];
} else {
// No match found
return 'no-match';
}
}
此函数将正确匹配以下测试数据的所需 DIV 元素:
<div>Bye.</div><div>Hello!</div>
它还会在嵌套的 DIV 元素的最里面正确地找到“HELLO”:
<div>
<div>
Hello world!
</div>
</div>
但是,如前所述,它不会找到位于非最内层嵌套 DIV 元素中的“HELLO”字符串,如下所示:
<div>
Hello,
<div>
world!
</div>
</div>
要做到这一点是一个复杂得多的解决方案。
在很多情况下,此解决方案可能会失败。再来一次。我建议使用 HTML 解析器。