preg_match_all提取数字需先取$matches[0]或$matches[1]再array_map('intval'/'floatval',...)转类型,否则array_sum会因二维数组或字符串类型报错。

preg_match_all 提取字符串里的数字,但 sum() 会出错
直接 array_sum() 提取结果数组会报 Warning:「Array to string conversion」——因为 preg_match_all() 返回的是二维数组,匹配结果在 $matches[0] 或 $matches[1] 里,不是扁平数字列表。
- 必须先取到具体匹配子数组,比如
$matches[0](全部匹配项)或带捕获组的$matches[1] - 如果用了括号捕获(如
/(\d+)/),数字实际在$matches[1],$matches[0]是完整匹配串(可能含非数字字符) - 提取后要用
array_map('intval', ...)或array_map('floatval', ...)转类型,不能依赖自动转换——字符串"012"会被转成12,但"0x1F"这种会变成0
preg_match_all('/\d+/', 'abc12def34ghi5', $matches);
$nums = array_map('intval', $matches[0]); // [12, 34, 5]
$total = array_sum($nums); // 51
要保留小数?正则和类型转换都得改
默认 \d+ 只抓整数;想匹配 3.14、-2.5、.7,正则得升级,且 intval() 会截断小数,必须用 floatval()。
- 推荐正则:
/-?\d*\.?\d+/(简单场景),但会误抓123.或.e5;更稳一点用/-?\d+\.?\d*|\.\d+/ -
floatval()对空字符串返回0.0,对"abc"返回0.0,所以务必确保正则已过滤干净 - 注意浮点精度:
array_sum([0.1, 0.2])结果是0.30000000000000004,真要精确计算建议用bcadd()或转整数单位(如分→元)
preg_match_all('/-?\d+\.\d+|-?\.\d+|-?\d+/', '价格:-19.99元,折扣.5,上限100', $matches);
$nums = array_map('floatval', $matches[0]); // [-19.99, 0.5, 100]
$total = array_sum($nums); // 80.51000000000001
性能敏感时别用 preg_match_all 做简单求和
如果字符串只是「纯数字用空格/逗号隔开」,比如 "12 34 5" 或 "12,34,5",用 preg_match_all 是杀鸡用牛刀,慢且易出错。
- 用
explode()+array_filter()+array_map()更快更可控 -
str_replace()预处理分隔符统一(如把中文顿号、空格、逗号全换为英文逗号),再explode() -
filter_var($v, FILTER_VALIDATE_FLOAT)比floatval()更严格,能筛掉无效值(如"12abc")
$s = "12,34、5";
$s = str_replace([',', '、', ' '], ',', $s);
$parts = array_filter(explode(',', $s), 'is_numeric');
$nums = array_map('floatval', $parts);
$total = array_sum($nums);
遇到 Unicode 数字(如阿拉伯数字、汉字数字)怎么办
\d 在 PHP 默认 PCRE 下只匹配 ASCII 数字 0–9,对 ١٢٣(阿拉伯数字)或 一二三 完全无效。
立即学习“PHP免费学习笔记(深入)”;
- 加
u修饰符只是让正则支持 UTF-8,\d含义不变;要匹配所有 Unicode 数字,得用\p{N} -
mb_convert_kana()可把全角 ASCII 数字(如123)转为半角,但对汉字数字(一、二、三)需单独映射表 -
intl扩展的NumberFormatter能解析汉字数字,但开销大,日常不推荐
// 匹配任意 Unicode 数字字符(包括 ١٢٣、๑๒๓)
preg_match_all('/\p{N}+/u', '价格:١٢٣円', $matches);
// 然后用 intval() 仍可正常转,PHP 会识别 UTF-8 编码的数字字符
该处理的边界情况其实就那几个:正则没抓全、类型没转对、小数精度失控、Unicode 漏掉。真正卡住人的,往往是第 2 步——以为 $matches[0] 就是数字数组,结果 sum 出来是 0。











