如何在正则表达式中表达“重复此部分”?

时间:2015-09-01 10:01:33

标签: python regex

假设我想匹配一个这样的字符串:

  

123(432)123(342)2348(34)

我可以将123[\d]*(432)等数字与\([\d]+\)匹配。

如何通过重复两种模式中的任何一种来匹配整个字符串?

我尝试了[[\d]* | \([\d]+\)]+,但这是不正确的。

我正在使用python re模块。

3 个答案:

答案 0 :(得分:3)

我认为你需要这个正则表达式:

"^(\d+|\(\d+\))+$"

为了避免灾难性的回溯,你需要将它改为像这样的正则表达式:

"^(\d|\(\d+\))+$"

答案 1 :(得分:2)

您可以使用字符类来匹配整个字符串:

[\d()]+

但是,如果您想在不同的组中匹配单独的部分,可以根据需要使用re.findall和空格正则表达式,例如:

>>> import re
>>> s="123(432)123(342)2348(34)"
>>> re.findall(r'\d+\(\d+\)',s)
['123(432)', '123(342)', '2348(34)']
>>> 

或者:

>>> re.findall(r'(\d+)\((\d+)\)',s)
[('123', '432'), ('123', '342'), ('2348', '34')]

或者您可以使用\d+获取所有数字:

>>> re.findall(r'\d+',s)
['123', '432', '123', '342', '2348', '34']

如果您想重复匹配模式\d+\(\d+\),可以使用以下正则表达式:

(?:\d+\(\d+\))+

答案 2 :(得分:1)

你可以用这种模式实现它:

^(?=.)\d*(?:\(\d+\)\d*)*$

demo

(?=.)确保至少有一个字符(如果您想允许空字符串,请删除它)。

\d*(?:\(\d+\)\d*)*是一个展开的子模式。说明:使用bactracking正则表达式引擎,当你有一个像(A|B)*这样的子模式,其中A和B是互斥的(或者至少当A或B的结尾分别与B的开头匹配时)或者A),您可以像这样重写子模式:A*(BA*)*B*(AB*)*。对于您的示例,它替换(?:\d+|\(\d+\))* 这种新形式更有效:它减少了获得匹配所需的步骤,避免了最终的bactracking的很大一部分。

请注意,如果您使用atomic group (?>....)模拟this trick (?=(....))\1并使用前瞻自然是原子的事实,则可以进一步改进它:

^(?=.)(?=(\d*(?:\(\d+\)\d*)*))\1$

demo (比较先前版本所需的步骤数,并检查调试器以查看会发生什么)

注意:如果您不想在括号中包含两个连续数字,则只需在非捕获组内更改量词* +并添加{{1在模式的末尾,在锚(?:\(\d+\))?之前:

$

^(?=.)\d*(?:\(\d+\)\d+)*(?:\(\d+\))?$