这是你的正则表达式匹配的方式 no and little risk :
no and little risk
正则表达式中的一个分支是 ...|(?<!\bno)(?<!low).+risk 。
...|(?<!\bno)(?<!low).+risk
正则表达式引擎首先在目标字符串中的每个位置尝试匹配,从头开始:
no and little risk ^
第一个约束是当前位置不能在单词边界后跟“no”(由于 (?<!\bno) )。满足此条件:目标字符串的开头前面没有任何内容。
(?<!\bno)
第二个限制是当前位置不能在“低”之前(由于 (?<!low) )。这种情况也得到满足(见上文)。
(?<!low)
然后我们匹配一个或多个非换行符,但尽可能多地匹配它们(这是 .+ 部分)。这里我们最初使用整个字符串:
.+
no and little risk ------------------^
但是正则表达式需要匹配 risk ,失败(目标字符串中没有剩余字符)。这导致 .+ 在发生这种情况之前,要回溯并消耗越来越少的字符:
risk
no and little risk --------------^
在此刻, risk 成功匹配,正则表达式完成。
基本问题是你想要做的就是 (?<!\bno.+)(?<!low.+)risk ,但你写的是 (?<!\bno)(?<!low).+risk 。这是两个非常不同的东西!
(?<!\bno.+)(?<!low.+)risk
(?<!\bno)(?<!low).+risk
前者意味着“匹配'风险',但只有在字符串中的任何地方都没有'否'或'低'之前(在'风险'之前最多1个字符)”。后者意味着“匹配任何非空子字符串后跟'风险',只要它没有'不'或'低'之前”。这使得正则表达式引擎可以自由地查找字符串中的任何匹配位置,只要它不是紧跟在“no”或“low”之后,并且在某处后面跟着“。+ risk”。
不幸 (?<!\bno.+) 不是有效的正则表达式,因为后置断言必须具有固定长度。
(?<!\bno.+)
一种可能的解决方法是执行以下操作:
^(?!.*(?:\bno|low).+risk).*risk
这说:从字符串的开头开始,首先确保在任何地方都没有“no”或“low”,然后是“risk”,然后在字符串中的任何位置匹配“risk”。
这与(假设的)可变宽度后视版本并不完全相同,因为那个版本会匹配
risk no risk ^^^^
由于存在“风险”而前面没有“否”,而这种解决方法首先发现
risk no risk ^^^^^^^
并立即拒绝整个字符串。