regex Python正则表达式匹配表达式{m,n}未按预期工作

l5tcr1uw  于 2023-05-30  发布在  Python
关注(0)|答案(3)|浏览(141)

我试图从文本字符串say =“Rate of increase 12.5% per annual”中提取百分比值,其中百分比可以是小于100的任何小数。当我尝试

re.sub(r'.*([0-9]{1,2}\.[0-9]).*',r'\1', text)

返回2.5。我认为,如果它是{1,2}?,结果应该是这样。{1,2}+也会返回 "..multiple match.." 错误。虽然我已经使用了一些替代的解决方案,但我很想知道我错在哪里。

0aydgbwb

0aydgbwb1#

正如InSync所评论的那样,您的模式的问题是模式开头和结尾的.* 是贪婪的,这意味着它匹配尽可能多的字符。
在您的示例文本字符串“Rate of increase 12.5% per annum”中,模式开头的.* 匹配整个字符串,直到小数点前的最后一位(在本例中为1)。然后,捕获组([0-9]{1,2}.[0-9])匹配剩余的数字(2.5),因为它满足小数点前有一个或两个数字并且小数点后至少有一个数字的模式要求。最后,模式末尾的.* 匹配字符串的其余部分(“per annual”)。
要纠正这个问题,可以通过添加一个?在.* 之后:

re.sub(r'.*?([0-9]{1,2}\.[0-9]).*', r'\1', text)

此修改使.*?匹配尽可能少的字符,确保捕获组([0-9]{1,2}.[0-9])仅捕获所需的十进制数。
有了这个变化,修正后的图案将提取出预期的结果,即12.5
注意:如果百分比值可以是小于100的任何小数,则可以考虑修改正则表达式模式,以允许小数点前的数字大于9。您可以使用{1,2}来匹配一个或两个数字,也可以使用{1,2}后跟(?<!\d)匹配一个或两个数字,前提是它们前面没有另一个数字。在这种情况下,你必须这样做:

result = re.sub(r'.*?(?<!\d)([0-9]+\.[0-9]).*', r'\1', text)

这个修改过的模式通过使用一个负的lookbehindAssert(?)<!\d)检查匹配的十进制数前面是否没有数字。
希望对你有帮助!

roqulrg3

roqulrg32#

我会做:

match = re.search(r'\b[0-9]{1,2}\.[0-9]', text)
# match is None if not found
# otherwise the result is in match[0]

其中\b记录为:* “匹配空字符串,但仅在单词的开头或结尾。"*

u1ehiz5o

u1ehiz5o3#

如果你的目标是提取匹配,那么你可以尝试下面的代码行:

re.sub(r'.*([0-9][0-9].[0-9]).*',r'\1', text)

相关问题