Python正则表达式匹配字符串数字:为何单数字无法匹配?
正则匹配数字时单个数字无法匹配的问题解析
问题重现
你在Python 2.7里用正则匹配字符串中的数字时,遇到了单个数字无法被匹配的问题。你的初始代码如下:
import re s = '858 1790 -156.25 2' re_matchData = re.compile(r'\-?\d{1,10}\.?\d{1,10}') data = re.findall(re_matchData, s) print data
执行后输出:
['858', '1790', '-156.25']
而当你把正则中的\d{1,10}改成\d{0,10}后,就能匹配到单个数字2了:
re_matchData = re.compile(r'\-?\d{0,10}\.?\d{1,10}')
输出变为:
['858', '1790', '-156.25', '2']
\d{1,10} 和 \d{0,10} 的核心区别
这两个都是正则中的数量限定符,区别非常明确:
\d{1,10}:要求匹配1到10个连续的数字字符——也就是说必须至少有1个数字,最多不能超过10个。\d{0,10}:允许匹配0到10个连续的数字字符——可以没有数字(匹配空内容),最多10个数字。
原写法的问题所在
咱们拆解一下你最初的正则r'\-?\d{1,10}\.?\d{1,10}':
\-?:匹配可选的负号\d{1,10}:匹配至少1个数字(作为整数部分)\.?:匹配可选的小数点\d{1,10}:匹配至少1个数字(作为小数部分)
问题就出在第4部分:单个数字2没有小数部分,\.?可以匹配空,但后面的\d{1,10}要求必须有至少1个数字,这时候2后面没有更多数字了,整个正则就无法匹配到它。
而改成\d{0,10}后,第4部分允许匹配0个数字,所以当没有小数部分时,这部分能匹配空,整个正则就能成功匹配单个数字了。不过这个修改有个隐患:它会匹配像单独的-或者.这类无效的“数字”,如果你的字符串里有这类字符,会被误匹配出来。
正确的修正方案
我们需要写一个既能匹配整数、小数(包括正负),又能匹配单个数字,还不会误匹配无效内容的正则。推荐写法如下:
# 不限制数字长度的版本 re_matchData = re.compile(r'-?\d+(\.\d+)?')
如果需要和你原来的需求一样,限制整数部分最多10位、小数部分最多10位,可以改成:
# 限制长度的版本 re_matchData = re.compile(r'-?\d{1,10}(\.\d{1,10})?')
正则解释:
-?:匹配可选的负号(这里不需要转义,因为它不在字符组的开头,转义也不影响)\d+(或\d{1,10}):匹配至少1个数字(整数部分,确保不会匹配空内容)(\.\d+)?(或(\.\d{1,10})?):整个括号内是可选的小数部分——\.匹配小数点,\d+匹配至少1个小数位,外面的?表示这部分可以不存在(对应整数的情况)。
用这个正则匹配你的测试字符串,得到的结果就是['858', '1790', '-156.25', '2'],完全符合预期,还不会误匹配无效内容。
内容的提问来源于stack exchange,提问作者Deus_Lysenko
相关产品推荐
相关产品推荐

