假设我想匹配一个这样的字符串:
123(432)123(342)2348(34)
我可以将123
与[\d]*
和(432)
等数字与\([\d]+\)
匹配。
如何通过重复两种模式中的任何一种来匹配整个字符串?
我尝试了[[\d]* | \([\d]+\)]+
,但这是不正确的。
我正在使用python re模块。
答案 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*)*$
(?=.)
确保至少有一个字符(如果您想允许空字符串,请删除它)。
\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+\))?$