要匹配包含某些单词的字符串,我可以使用模式“/.*word.*/”.但是我如何匹配一个不包含这个单词的字符串?
例:
我需要在一个大文本中找到一个子字符串,它由两个标签括起来,并且里面有一些像“Hello”这样的字符串.我想出的最好的:
"@
但它也会匹配顺序:
而且我不想匹配第一对div标签 – 因此我想要替换“.*?”用“匹配任何字符串,除了不包含”之类的东西.
测试用例:
对于输入字符串:
我需要抓住
解决方法:
该问题的更好标题可能是:“匹配包含特定子字符串的DIV元素.”首先,必须说正则表达式不是这项工作的最佳工具.使用HTML解析器解析标记,然后在每个DIV元素的内容中搜索所需的子字符串会好得多.也就是说,由于您不想了解更多关于如何使用正则表达式来匹配其他内容的东西,因此以下描述了使用正则表达式执行此操作的有限方法.
正如Dogbert正确指出的那样,这个问题确实是Regular expression to match string not containing a word?的重复.但是,我看到你已经查看了这个问题,但需要知道如何将这种技术应用于子模式.
要匹配不包含特定单词(或单词)的字符串(子模式)的一部分,您需要在每个字符之前应用负前瞻断言检查.以下是打开和关闭DIV标记之间文本的方法.请注意,当仅使用单个正则表达式时,因为DIV元素可能是嵌套的,所以在嵌套DIV元素的“最里面”内找到“HELLO”是合理的.
伪代码:
>匹配打开的DIV标记.
> Lazily匹配零个或多个字符,每个字符不是< 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"
(?: # 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.
%six';
if (preg_match($re, $text, $matches)) {
// Match found.
return $matches[0];
} else {
// No match found
return 'no-match';
}
}
此函数将正确匹配以下测试数据的所需DIV元素:
它还将在嵌套的DIV元素的最里面正确找到“HELLO”:
Hello world!
但是,如前所述,它不会找到位于非最内层嵌套DIV元素中的“HELLO”字符串,如下所示:
Hello,
world!
要做到这一点是一个更复杂的解决方案.
在很多情况下,此解决方案可能会失败.再来一次.我建议使用HTML解析器.
标签:php,regex,regex-negation
来源: https://codeday.me/bug/20190614/1237315.html