0

我试图写一个正则表达式找到 两边正好有 3 个大写字母的所有字符

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

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

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

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

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

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

谢谢。

4

4 回答 4

1

您需要将负前瞻放在正前:

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

你也可以通过后视来做到这一点:

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

它不违反“固定长度后视”规则,因为环视本身不消耗任何字符。


编辑(关于固定长度的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 的风格中。

不,任何形式的前瞻都没有类似的限制。

于 2012-05-25T21:20:24.067 回答
0

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

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

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

于 2012-05-26T07:11:05.027 回答
0

取出积极的前瞻对我有用。

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

'ABCdDEF' 'ABCfDEF' 'HHHhhhHHHH' 'jjJJjjJJJ' JJJjJJJ 匹配 ABCdDEF ABCfDEF JJJjJJJ

于 2012-05-25T20:25:44.923 回答
0

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

您也可以使用单个断言,如下所示:

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

与后视相同:

 '(?<=[^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)中间,如果您希望空间匹配,请将其更改回来。

PS 你在解决Python 挑战吗?:)

于 2012-05-25T20:26:16.873 回答