正则表达式负面预测正好围绕一个字母的3个大写字母

时间:2012-05-25 20:16:43

标签: regex lookahead negative-lookahead

我试着写一个正则表达式找到所有的字符 两侧大致 3个大写字母

以下正则表达式查找字符左侧正好有3个大写字母的所有字符,以及右侧3 (或更多)

'(?<![A-Z])[A-Z]{3}(.)(?=[A-Z]{3})'

尝试使用正则表达式将右侧限制为不超过3个大写:

'(?<![A-Z])[A-Z]{3}(.)(?=[A-Z]{3})(?![A-Z])'

我没有得到任何结果,将(?![A-Z])添加到第一个正则表达式时似乎失败了。

有人可以解释我的问题并提出解决方法吗?

感谢。

4 个答案:

答案 0 :(得分:1)

你需要将否定的前瞻置于中:

(?<![A-Z])[A-Z]{3}.(?=[A-Z]{3}(?![A-Z]))

你也可以用lookbehind做到这一点:

(?<=(?<![A-Z])[A-Z]{3}).(?=[A-Z]{3}(?![A-Z]))

它没有违反“固定长度lookbehind”规则,因为lookarounds本身不消耗任何字符。


编辑(关于固定长度的lookbehind):在所有支持lookbehind的风格中,Python是最不灵活的。在大多数风格(例如Perl,PHP,Ruby 1.9+)中,您可以使用:

(?<=^[A-Z]{3}|[^A-Z][A-Z]{3}).

...匹配前面带有正好三个大写ASCII字母的字符。第一种选择 - ^[A-Z]{3} - 开始寻找三个位置,而第二个 - [^A-Z][A-Z]{3} - 完全返回四个位置。在Java中,您可以将其减少为:

(?<=(^|[^A-Z])[A-Z]{3}).

...因为它在编译时做了一些额外的工作,以确定最大的后视长度将是四个位置。在.NET和JGSoft中,任何事情都会发生;如果它在任何地方合法,那么它在合法的背后是合法的。

但在Python中,lookbehind子表达式必须匹配单个固定数量的字符。如果你曾经多次反对这个限制,那么你可能不会期望这样的事情发挥作用:

(?<=(?<![A-Z])[A-Z]{3}).

至少我没有。它比Java版本更简洁;它如何在Python中工作?但它确实有效,在Python和其他支持lookbehind的风格中。

不,没有任何类似的前瞻限制,无论如何。

答案 1 :(得分:0)

取出积极的前瞻为我工作。

(?<![A-Z])[A-Z]{3}(.)([A-Z]{3})(?![A-Z])

'ABCdDEF''ABCfDEF''HHHhhhHHHH''jjJJjjJJJ'JJJjJJJ 火柴 ABCdDEF ABCfDEF JJJJJJJ

答案 2 :(得分:0)

我不确定正则表达式引擎应该如何使用多个前瞻断言,但是你正在使用的那个可能对此有自己的看法。

您也可以使用以下单个断言:

 '(?<![A-Z])[A-Z]{3}(.)(?=[A-Z]{3}[^A-Z])'

与lookbehind相同:

 '(?<=[^A-Z][A-Z]{3})(.)(?=[A-Z]{3}[^A-Z])'

这将在行的开头和结尾匹配模式时出现问题。 我想不出一个合适的解决方案,但可能有一个肮脏的技巧:例如,在整行的开头和结尾添加一个空格(或其他东西),然后执行匹配。

$ echo 'ABCdDEF ABCfDEF HHHhhhHHHH AAAaAAAbAAA jjJJJJjJJJ JJJjJJJ' | sed 's/.*/ & /' | grep -oP '(?<=[^A-Z][A-Z]{3})(\S)(?=[A-Z]{3}[^A-Z])'
d
f
a
b
j

请注意,我在中间将(.)更改为(\S),如果您希望空间匹配,请将其更改回来。

P.S。你在解决The Python Challenge吗? :)

答案 3 :(得分:0)

由于前瞻模式与后面的模式相同,您还可以使用continue anchor \G

/(?:[A-Z]{3}|\G[A-Z]*)(.)[A-Z]{3}/

如果三个大写字母位于单个字符之前或最后一个匹配位置停止(可选地后跟其他大写字母),则返回匹配。