Sta*_*bie 28 regex regex-negation
假设以下字符串:
aaa bbb ccc
bbb aaa ccc
Run Code Online (Sandbox Code Playgroud)
aaa只要它不在字符串的开头,我想匹配.我试图通过这样做来否定它:
[^^]aaa
Run Code Online (Sandbox Code Playgroud)
但我不认为这是对的.用preg_replace.
Joe*_*Joe 57
您可以使用后面的外观来确保它不在开头. (?<!^)aaa
Wik*_*żew 21
自从我通过谷歌搜索来到这里,并且对一个没有使用外观的解决方案感兴趣,这是我的2美分.
该[^^]aaa模式匹配以外的字符^,然后3 aš 任何地方在字符串中.这[^...]是一个否定的字符类,^不被视为特殊字符.注意第一个^是正确的,[因为它表示否定,第二个只是一个字面符号.
因此,a ^不能在里面[...]表示字符串的开头.
一个解决方案是使用任何负面的外观,这两个将同样有效:
(?<!^)aaa
Run Code Online (Sandbox Code Playgroud)
和先行:
(?!^)aaa
Run Code Online (Sandbox Code Playgroud)
为什么前瞻也有效?Lookarounds是零宽度断言,锚也是零宽度 - 它们不消耗文本.从字面上讲,(?<!^)检查当前位置左侧(?!^)是否没有字符串位置的开始,并检查当前位置右侧是否没有字符串位置的开始.正在检查相同的位置,这就是为什么两者都运作良好.
anu*_*ava 12
如果你不想使用lookbehind,那么使用这个正则表达式:
/.(aaa)/
Run Code Online (Sandbox Code Playgroud)
并使用matched group # 1.
这种情况是我第一次看到lookarounds outperform \K。有趣的。
通常捕获组和环视需要额外的步骤。但是由于此任务的性质,正则表达式引擎可以更快地导航字符串以搜索aaa然后回头查找字符串锚点的开始。
我将添加几个\K模式进行比较。
我正在使用s模式修饰符,以防前导字符可能是换行符(.通常不匹配)。我只是想我会添加这个考虑来抢先解决我可能提出的边缘案例。
同样,这是一个有启发性的场景,因为在我处理过的所有其他正则表达式案例中,\K其他技术都胜过。
步数比较矩阵:
| `~.\Kaaa~s` | `~.+?\Kaaa~s` | `(?<!^)aaa` | `(?!^)aaa` | `.(aaa)` |
--------------|-------------|---------------|-------------|------------|----------|
`aaa bbb ccc` | 12 steps | 67 steps | 8 steps | 8 steps | 16 steps |
--------------|-------------|---------------|-------------|------------|----------|
`bbb aaa ccc` | 15 steps | 12 steps | 6 steps | 6 steps | 12 steps |
Run Code Online (Sandbox Code Playgroud)
要点是:要了解您的模式的效率,请将它们吐到 regex101.com 并比较步数。
另外,如果你知道什么串您正在寻找和你并不需要一个正则表达式,那么你就应该使用strpos()最佳实践的问题(和公正的检查返回值是> 0)
...换句话说:
if (strpos($haystack, 'aaa')) {
// 'aaa' is "truthy"
// 'aaa' is found and not positioned at offset zero
}
Run Code Online (Sandbox Code Playgroud)