正则表达式匹配ms前数值:解决多空格下的匹配异常问题
问题场景
给定以下模型层耗时文本:
ConvolutionDepthWise Conv_3 1.66ms | [ 32, 32, 6 *4] -> [ 16, 16, 6 *4] kernel: 3 x 3 stride: 2 x 2
Convolution Conv_4 3.08ms | [ 16, 16, 6 *4] -> [ 16, 16, 6 *4] kernel: 1 x 1 stride: 1 x 1
Convolution Conv_6 2.67ms | [ 32, 32, 6 *4] -> [ 32, 32, 6 *4] kernel: 1 x 1 stride: 1 x 1
ConvolutionDepthWise Conv_8 1.36ms | [ 32, 32, 6 *4] -> [ 16, 16, 6 *4] kernel: 3 x 3 stride: 2 x 2
需要匹配ms前的纯数字(如1.66、3.08),但使用正则re.findall(r"\s*(.*?)ms", text)时,结果会包含开头的空格,无法得到干净的数字。
解决方案
核心思路是精准匹配数字格式,而非用模糊的任意字符匹配,这样就能避免捕获空格:
方法1:直接匹配带小数点的数字
使用正则r"(\d+\.\d+)ms",其中:
\d+:匹配1个或多个数字\.:匹配小数点(需转义,因为.在正则中代表任意字符)(\d+\.\d+):捕获组,仅提取目标数字部分
代码示例:
import re text = """ConvolutionDepthWise Conv_3 1.66ms | [ 32, 32, 6 *4] -> [ 16, 16, 6 *4] kernel: 3 x 3 stride: 2 x 2 Convolution Conv_4 3.08ms | [ 16, 16, 6 *4] -> [ 16, 16, 6 *4] kernel: 1 x 1 stride: 1 x 1 Convolution Conv_6 2.67ms | [ 32, 32, 6 *4] -> [ 32, 32, 6 *4] kernel: 1 x 1 stride: 1 x 1 ConvolutionDepthWise Conv_8 1.36ms | [ 32, 32, 6 *4] -> [ 16, 16, 6 *4] kernel: 3 x 3 stride: 2 x 2""" result = re.findall(r"(\d+\.\d+)ms", text) print(result) # 输出: ['1.66', '3.08', '2.67', '1.36']
方法2:匹配带前置空格的数字(更精准)
如果要避免误匹配文本中其他位置的ms(比如某个字符串里包含ms但不是耗时),可以加上前置空格匹配:r"\s+(\d+\.\d+)ms",其中\s+匹配1个或多个空格,确保只捕获耗时数字。
原正则问题分析
原正则r"\s*(.*?)ms"的问题在于:
.*?是非贪婪匹配任意字符,虽然\s*会匹配前置空格,但如果文本中数字前存在其他非空格字符(或\s*未完全匹配空格时),就会把多余内容也捕获进去。- 用模糊匹配代替精准的数字格式匹配,稳定性差,容易捕获到无关内容。
内容的提问来源于stack exchange,提问作者Mactarvish

