preg_match()仅匹配首个结果并返回1/0/false,适合存在性验证;preg_match_all()提取全部匹配,返回总数并将结果按标志存入$matches,需注意重叠匹配、中文修饰符u及分隔符规范。

preg_match() 只找第一个匹配就停,preg_match_all() 扫完整个字符串,一个不漏。
preg_match() 适合判断“有没有”或取第一个值
它返回 1(匹配成功)、0(没匹配到)或 false(正则写错了)。传了 $matches 参数才会填充捕获组,$matches[0] 是整个匹配内容,$matches[1] 是第一个括号里的子匹配。
- 常见错误:用
preg_match()提取所有邮箱,结果只拿到第一个 —— 它根本不会继续往后找 - 典型场景:验证手机号格式、检查 URL 是否含
https://、从 HTML 片段里提取第一个<title> - 性能上更轻量,尤其在大文本中只需确认存在性时,比
preg_match_all()快得多
preg_match_all() 必须用于“全量提取”
它返回匹配总数(整数),同时把所有结果按 $flags 指定的方式组织进 $matches。默认是 PREG_PATTERN_ORDER,即 $matches[0] 存全部完整匹配,$matches[1] 存所有第一个子组的匹配;换成 PREG_SET_ORDER 后,$matches[0] 就是第一次匹配的完整结果(含子组),$matches[1] 是第二次的……
- 容易踩的坑:
preg_match_all()不会自动跳过重叠匹配 —— 比如模式/aa/在"aaa"中只匹配一次(位置 0–1),不会在位置 1–2 再来一次,除非加PREG_OFFSET_CAPTURE配合手动偏移控制 - 中文处理必须加
u修饰符,否则/[\x{4e00}-\x{9fff}]+/会失效;分隔符别用/和中文路径冲突,改用#或~更稳 - 如果正则里用了命名捕获组(如
/(?<year>\d{4})/</year>),$matches['year']会直接可用,但同名组重复出现时,只保留最右边那次的值
分隔符和错误返回值必须对得上
两个函数都要求 $pattern 用成对分隔符包裹,比如 /abc/i、#^/user/\d+#。漏掉结尾分隔符或混用中文标点,就会报 Unknown modifier 'x' 这类警告。
立即学习“PHP免费学习笔记(深入)”;
-
preg_match()出错返回false,无匹配返回0—— 别用== true判断,要用=== 1或直接if ($ret)(因为1是真,0是假) -
preg_match_all()出错也返回false,但正常时返回的是匹配次数(可能是0),所以同样不能靠真假值判断成败 - 调试时可以用
preg_last_error_msg()看具体哪错,比如Compilation failed: missing )就是括号没配对
真正麻烦的是嵌套结构或变长边界(比如 HTML 标签里套标签),preg_match_all() 本身不支持递归匹配,这时候正则就不是最优解了 —— 该换 DOM 解析器的时候,别硬扛。



















