我有一个看起来像这样的正则表达式:
(\bee[0-9]{9}in\b)|(\bee[0-9]{9}[a-zA-Z]{2}\b)
现在如果输入字符串是匹配字符串ee123456789ab
的第二部分。|
但是,如果输入字符串的ee123456789in
第一部分|
消耗整个字符串,而第二部分没有更改以匹配字符串?我希望这两个部分|
都进行更改以匹配字符串,以便我知道这两个部分都能够匹配字符串。甚至可以使用正则表达式来做到这一点吗?
我有一个看起来像这样的正则表达式:
(\bee[0-9]{9}in\b)|(\bee[0-9]{9}[a-zA-Z]{2}\b)
现在如果输入字符串是匹配字符串ee123456789ab
的第二部分。|
但是,如果输入字符串的ee123456789in
第一部分|
消耗整个字符串,而第二部分没有更改以匹配字符串?我希望这两个部分|
都进行更改以匹配字符串,以便我知道这两个部分都能够匹配字符串。甚至可以使用正则表达式来做到这一点吗?
使用正则表达式是不可能的。如果其中任何部分匹配,则视为匹配。你必须用两个不同的表达式来做,看看是否都成功了。
您可以使用前瞻断言:
^(?=(ee[0-9]{9}in$)?)(?=(ee[0-9]{9}[a-zA-Z]{2}$)?)
\1
这将在和中捕获匹配项\2
;如果两者中的任何一个为空,则正则表达式的相应部分不匹配。
我已将单词边界锚点更改为字符串锚点的开始/结束,因为您正在测试整个字符串,而不仅仅是子字符串。
在 Python 中:
>>> import re
>>> r = re.compile(r"^(?=(ee[0-9]{9}in$)?)(?=(ee[0-9]{9}[a-zA-Z]{2}$)?)")
>>> m = r.match("ee123456789ab")
>>> m.group(1)
>>> m.group(2)
'ee123456789ab'
>>> m = r.match("ee123456789in")
>>> m.group(1)
'ee123456789in'
>>> m.group(2)
'ee123456789in'
解释:
^ # Start of string
(?= # Look ahead to see if it's possible to match...
( # and capture...
ee[0-9]{9}in # regex 1
$ # (end of string)
)? # (make the match optional)
) # End of lookahead
(?= # Second lookahead, same idea...
(
ee[0-9]{9}[a-zA-Z]{2}
$
)?
)
OR 是一个或无论如何,都无法解决这个问题。
正如@Tim 提到的,它可以通过前瞻来完成:
你可以站着不动,不止一次地看同一个文本。
因此,一种方法是不动地查看每个表达式,
每个表达式都是可选的。-
(?= ( ee [0-9]{9} in )? )
(?= ( ee [0-9]{9} [a-zA-Z]{3} )? )
这很糟糕,因为虽然位置会在最后一个
表达式之后前进,但它只会前进 1 个字符间位置。在全局上下文中搜索时,它还
允许重叠。
可以通过消耗一个字符来加快搜索速度 -
(?= ( ee [0-9]{9} in )? )
(?= ( ee [0-9]{9} [a-zA-Z]{3} )? )
.
当某些东西被消耗时,引擎会进行优化,
以块的形式前进(不知道它是如何决定的)。
如果这些表达式中包含其他表达式,则需要将
位置提前到此处,否则将不匹配。这也可以消除
文本的重叠匹配(如果这是一个目标)。
实际上很难避免重叠,除非您确定一个表达式会
比另一个长。如果是这样的话,那么你总是可以做一个有条件的
(如果有的话)来使用更大的文本 -
(?= ( ee [0-9]{9} in )? )
(?= ( ee [0-9]{9} [a-zA-Z]{3} )? )
(?(2) \2 | \1 )
而且,如果你知道一个是另一个的子集,你可以这样做 -
(?= ( ee [0-9]{9} in )? ) ( ee [0-9]{9} [a-zA-Z]{3} )
无论哪种方式,根据表达式的不同,在将
消费设计到正则表达式中时必须考虑很多以避免重叠。