filter_var() 配合 filter_sanitize_number_int 最稳妥提取字符串中的整数,它保留数字、+、-并删除其余字符,如 filter_var("a-12b+34c", filter_sanitize_number_int) → "-12+34";但需配合 preg_match_all() 提取多个独立整数,并用边界断言确保完整匹配。

用 filter_var() 提取字符串里的整数最稳妥
直接用正则容易漏掉边界情况,比如带符号、开头空格、科学计数法干扰。PHP 自带的 filter_var() 配合 FILTER_SANITIZE_NUMBER_INT 是专为这个设计的——它会删掉所有非数字字符(除了 +、-),且不改变原始顺序。
常见错误现象:有人用 intval() 或 (int) 强转,结果只拿到开头一段(比如 "123abc456" 变成 123),后面整数完全丢失。
- 只保留数字、
+、-,其他全删;filter_var("a-12b+34c", FILTER_SANITIZE_NUMBER_INT)→"-12+34" - 不自动拆分多个数,得配合
preg_match_all()一起用(见下一条) - 注意:它不会验证是否合法整数(比如
"++12"也会留下),后续建议加is_numeric()或filter_var($val, FILTER_VALIDATE_INT)校验
用 preg_match_all() 匹配所有独立整数
要从字符串里找出所有「完整的整数」(如 "abc-42 def123 ghi+7" 中提取 -42、123、+7),必须用正则匹配,且关键在「边界控制」——否则 1234 会被当成 1、12、123、1234 多次匹配。
推荐模式:/(?,意思是:前面不能是数字、后面也不能是数字,中间可选符号 + 数字串。
立即学习“PHP免费学习笔记(深入)”;
preg_match_all('/(? → <code>['-42', '123', '+7']- 如果不需要符号,去掉
[+-]?;如果允许前导零(如"007"),保持\d+即可(但注意 PHP 整数解析时前导零可能被当八进制) - 别用
^\d+$——那是匹配整行,不是提取子串
intval() 和 (int) 的行为差异与陷阱
这两个看似一样,实际对异常输入处理不同:intval() 默认按十进制解析,遇到非数字立即截断;(int) 在某些老版本 PHP 中会尝试识别十六进制(如 "0x1A"),但新版已统一为十进制。真正危险的是它们都只返回第一个数。
-
intval(" -0012abc34")→-12(跳过空格,读到a停止) -
(int)" -0012abc34"→-12(行为一致,但不可控) - 如果源字符串含小数点(如
"12.34"),两者都返回12,但这是「截断」而非「四舍五入」,且无法得知原值是否为浮点 - 绝对不要用它们代替提取逻辑——它们不是为多整数场景设计的
性能和兼容性提醒:别在循环里反复编译正则
如果要在高频循环中做整数提取(比如日志逐行解析),preg_match_all() 的正则会被重复编译,PHP 7.4+ 虽有缓存,但显式使用 preg_quote() 或提前定义常量正则字符串更稳。
- 把正则写成常量:
define('INT_PATTERN', '/(?,再传给 <code>preg_match_all(INT_PATTERN, $str, $m) - 如果确定字符串只含 ASCII 数字和符号,用
mb_系列函数无意义,反而慢;preg_match_all()默认就是单字节安全的 - PHP 8.0+ 支持
PREG_UNMATCHED_AS_NULL,但整数匹配一般用不到;重点还是边界断言写对,否则空匹配或重叠匹配会让结果错乱
最易被忽略的一点:正则中的 ^ 和 $ 是行首/行尾锚点,不是字符串首尾——如果没加 m 修饰符,^ 对换行符后的内容就失效了;而整数提取几乎永远不需要它们。











