php怎么提取字符串数字 php从字符串中找数字【技巧】

5次阅读

php怎么提取字符串数字 php从字符串中找数字【技巧】

preg_match_all 提取字符串中所有数字

php 里最可靠、最常用的方法就是用 preg_match_all 配合正则匹配数字。别用 str_split循环判断 ASCII,既慢又漏负数、小数、科学计数法。

常见错误现象:只匹配整数却漏掉 "-12.34""1e5";或用 is_numeric() 判断单个字符,结果把 ".""e" 当成数字。

  • 提取所有连续数字(含负号和小数点):preg_match_all('/-?d+.?d*/', $str, $matches),但注意这会把 "12.34.56" 拆成 ["12.34", "56"]
  • 更严谨匹配浮点数(推荐):preg_match_all('/-?d+.?d*(?:[eE][+-]?d+)?/', $str, $matches),能覆盖 "-3.14e-2"
  • 如果只要整数(不含小数、指数),用 /'-?d+'/' 即可,性能略好

filter_var + FILTER_SANITIZE_NUMBER_INT / Float 的坑

filter_var 看起来简单,但实际不适合“提取”,它本质是“清洗”——把非数字字符全删掉,再拼一起,容易串号。

使用场景:你只是想快速清理用户输入的电话、价格字段,不关心原始位置或分组。

立即学习PHP免费学习笔记(深入)”;

  • filter_var($str, FILTER_SANITIZE_NUMBER_INT) 会删掉所有非数字和负号,"abc-12def34""-1234"(不是 ["-12", "34"]
  • FILTER_SANITIZE_NUMBER_FLOAT 还会保留小数点和 e,但同样不区分字段边界,"x1.2y3.4z""1.23.4",明显错
  • 它不返回数组,没法知道数字原来在哪儿,也不支持自定义分隔逻辑

intval / floatval 在字符串开头有数字时的行为

这两个函数不是提取工具,而是类型转换函数——它们只解析字符串**开头**的数字部分,遇到第一个非数字就停。

容易踩的坑:以为 intval("abc123") 能拿到 123,结果是 0;而 intval("123abc")123,看起来对,但完全忽略后面可能还有数字。

  • intval("42px")42,但 intval("px42")0
  • floatval("3.14abc")3.14floatval("abc3.14")0.0
  • 它们无法处理多个独立数字,也不报错,静默失败,调试时很难发现

性能与兼容性提醒

正则方案在 PHP 7.4+ 和 8.x 下表现稳定,preg_match_all 比循环 + ctype_digit 快 3–5 倍(尤其长字符串)。但要注意 PCRE JIT 编译开销——如果正则固定,建议提前编译(preg_replace_callback 不适用,但 preg_match_all 可缓存 pattern)。

  • PHP 8.2+ 开始,/u 修饰符对纯 ASCII 数字无影响,但若字符串含 Unicode 数字(如阿拉伯数字),需显式加 u 并用 p{N}
  • 避免用 mb_ereg,已废弃且慢;也别用 strtok 配合 is_numeric,逻辑复杂还易出错
  • 真正难的不是“怎么拿数字”,而是“怎么定义你要的数字”——要不要负号?是否接受千分位逗号?是否允许空格分隔?这些决定了正则怎么写,而不是换函数
text=ZqhQzanResources