Python正则表达式命名分组

4

我试图构建一个正则表达式来捕获任何数字(整数,浮点数,带科学计数法或不带)。 我使用组来使得如果需要更新某些内容,只需更新一行即可。这是我正在做的:

intNumber = r"(?P<Integer>-?(0|[1-9]+[0-9]*))" # Integer
floatNumber = r"(?P<Float>"+intNumber+r"\.[0-9]+)" # Float
sciNumber = r"(?P<Scientific>"+floatNumber+r"(e|E)(-|\+)?[0-9]+)" # Scientific
anyNumber = r"(?P<AnyNumber>"+sciNumber+"|(?P=Integer)|(?P=Float))" # Any number

问题在于,尽管每个正则表达式单独使用时都能正常工作,但当我将它们全部组合在 anyNumber 中并使用 or (|) 时,它仅捕获科学计数法数字,而不是其他数字。我做错了什么? 编辑:为了改进我的问题,是否有可能生成动态的正则表达式(考虑到简单维护),同时又足够灵活,使我能够单独使用其组件,避免出现重新定义组和方便地对组进行命名等问题?我知道我可能要求过多了。

请尝试访问http://ideone.com/fu9eOy - Wiktor Stribiżew
2个回答

0

(?P=Integer)是一个命名的后向引用,它与命名为"Integer"的捕获组匹配相同文本(而不是递归组子模式!)。(?P=Float)也是如此。这意味着您需要使用该模式本身,而不是后向引用。

同时,如果您计划以这种方式动态构建正则表达式,则无法使用命名的后向引用。请使用非捕获组,您的模式构建将类似于以下内容:

import re
intNumber = r"-?(?:0|[1-9]+[0-9]*)" # Integer
floatNumber = intNumber+r"\.[0-9]+" # Float
sciNumber = floatNumber+r"[eE][-+]?[0-9]+" # Scientific
anyNumber = r"{0}|{1}|{2}".format(sciNumber,floatNumber,intNumber) # Any number
print(re.findall(anyNumber, '12 12.34 12.34E-34'))

请查看Python演示


好的,谢谢!但是如果我还想引用intNumber组整数或者group Float,因为我也会单独使用它们(而不仅仅是为了制作anyNumber正则表达式),那么我就需要有捕获组。在这种情况下,如果我能有命名捕获组就太好了。请看我的问题编辑 :) - capitan
re 正则表达式中,您不能使用两个具有相同名称的命名组。如果您使用您的模式定义了 anyNumber,如 r"{0}|{1}|{2}".format(sciNumber,floatNumber,intNumber),则会引发异常。您可以考虑使用 PyPi 正则表达式模块,或者忘记这样深层次的命名。 - Wiktor Stribiżew

0
我最终做了以下事情:
intNumber_re = r"(?P<Integer>-?(0|[1-9]+[0-9]*))" # Integer
floatNumber_re = r"(?P<Float>"+intNumber_re+r"\.[0-9]+)" # Float
sciNumber_re = r"(?P<Scientific>"+floatNumber_re+r"[eE][-\+]?[0-9]+)" # Scientific
groupNames_re = r'(\?P<Integer>)|(\?P<Float>)|(\?P<Scientific>)'
anyNumber_re = r"(?P<AnyNumber>{0}|{1}|{2})".format(re.sub(groupNames_re,'?:',sciNumber_re),
               re.sub(groupNames_re,'?:',floatNumber_re),re.sub(groupNames_re,'?:',intNumber_re)) # Any number

实际上,我在使用re.sub()函数构建anyNumber RE时,会有效地删除组名称(正则表达式在groupNames_re中)。这有点丑陋,但它能够工作并给我想要的灵活性。感谢Wiktor提供的帮助,我最终使用了你的一部分代码 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接