如何用preg_match_all从字符串提取指定格式的带逗号数字?
解决方案
正确的正则表达式
针对你的需求,匹配带逗号、逗号前1-3位数字、逗号后仅1位数字的正则表达式如下:
/(?<!\d)-?\d{1,3},\d(?!\d)/
各部分说明:
(?<!\d):确保数字前面不是其他数字,避免从长数字(如1234,5)中误匹配子部分-?:支持可选的负号(如果需要匹配负数的话)\d{1,3}:匹配逗号前1到3位数字,:匹配分隔用的逗号\d:匹配逗号后恰好1位数字(?!\d):确保数字后面不是其他数字,避免误匹配长数字的子部分
代码实现
如果只需要提取第一个符合条件的数字,用preg_match即可:
$string = "P 1 BNN-01 HV A7weg letsel (Auto) A7 Re 138,3 HASKERHORNE."; $pattern = '/(?<!\d)-?\d{1,3},\d(?!\d)/'; if (preg_match($pattern, $string, $matches)) { $number = $matches[0]; echo $number; // 输出:138,3 }
如果字符串中可能存在多个符合条件的数字,用preg_match_all提取所有结果:
$string = "P 1 BNN-01 HV A7weg letsel (Auto) A7 Re 138,3 HASKERHORNE. More numbers: 45,6 and -7,8"; $pattern = '/(?<!\d)-?\d{1,3},\d(?!\d)/'; if (preg_match_all($pattern, $string, $matches)) { print_r($matches[0]); // 输出:Array ( [0] => 138,3 [1] => 45,6 [2] => -7,8 ) }
原正则的问题说明
你之前的正则^-?\d+(,\d+)*(\.\d+(e\d+)?)?$存在两个核心问题:
- 使用
^和$锚定了整个字符串,要求整个字符串必须是一个数字,而你的目标只是字符串中的一段子内容,因此无法匹配。 - 规则过于宽泛,允许多个逗号、小数点甚至科学计数法,不符合“逗号后仅1位数字”的严格要求。
内容的提问来源于stack exchange,提问作者Edwin Tjallings
相关产品推荐
相关产品推荐

