正则表达式:匹配模式,只要它不在开头

时间:2013-03-27 21:09:51

标签: regex regex-negation

假设以下字符串:

aaa bbb ccc
bbb aaa ccc

我希望匹配aaa,只要它不在字符串的开头即可。我试图通过做这样的事来否定它:

[^^]aaa

但我不认为这是对的。使用preg_replace

6 个答案:

答案 0 :(得分:42)

您可以使用后面的外观来确保它不在开头。 (?<!^)aaa

答案 1 :(得分:16)

由于我是通过谷歌搜索来到这里的,并且对一个没有使用外观的解决方案感兴趣,这是我的2美分。

[^^]aaa模式匹配^以外的字符,然后匹配字符串内的3 a s [^...]negated character class,其中^不被视为特殊字符。请注意^之后的第一个[是特殊的,因为它表示否定,第二个只是一个字面符号。

因此,^不能在[...]内表示字符串的开头。

解决方案是使用任何负面的外观,这两种方法同样有效:

(?<!^)aaa

和前瞻:

(?!^)aaa

为什么前瞻也有效? Lookarounds是零宽度断言,锚点也是零宽度 - 它们不消耗任何文本。从字面上讲,(?<!^)检查当前位置左侧是否没有字符串位置的开始,(?!^)检查当前位置右侧是否没有字符串位置的开始。正在检查相同的位置,这就是两者都运行良好的原因。

答案 2 :(得分:12)

如果您不想使用lookbehind,请使用此正则表达式:

/.(aaa)/

并使用matched group # 1

答案 3 :(得分:2)

这种情况是我第一次看到外观优于\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 |

摘要是:要了解模式的效率,请将它们吐入regex101.com并比较步数。

此外,如果您确切知道您正在寻找的子字符串,并且您不需要正则表达式模式,那么您应该使用strpos()作为最佳实践(并检查返回的值是否为> 0)。

答案 4 :(得分:0)

这将有助于找到您要找的内容:

(?<!^)aaa

使用示例:http://regexr.com?34ab2

答案 5 :(得分:0)

我来这里是为Google电子表格使用的re2引擎提供解决方案,该解决方案不支持环视。 但是这里的答案给了我使用以下内容的想法。 我不明白为什么我必须由捕获的小组代替,但是无论如何,它行得通。

  

aaa bbb ccc
  bbb aaa ccc

([^^])aaa

替换为:

$1zzz

重新使用:

  

aaa bbb ccc
  bbb zzz ccc