preg_quote 默认转义的12个正则特殊字符是:. \ + * ? [ ^ ] $ ( ) { } = ! | :;/ 不在其中,仅当显式传入 $delimiter 参数时才被转义。

preg_quote 默认转义的 12 个正则特殊字符有哪些
PHP 的 preg_quote 不是“按需转义”,它有一套固定清单:只要出现在 $str 中,就一律加反斜线。漏掉的关键往往不是“没转”,而是**误以为某些符号该转、其实不在清单里**。
它明确转义的字符共 12 个:. \ + * ? [ ^ ] $ ( ) { } = ! <code>> | : —— 注意,/ **不在其中**(除非你显式传入 $delimiter = '/')。
-
/只有在指定$delimiter参数时才被转义,否则完全不管 -
-和#在部分文档里被提及,但 PHP 8.0 实际行为中**不转义**(它们仅在特定上下文如字符类[a-z]或注释模式中才有意义,preg_quote不处理语义) -
"、'、(空格)、,、;等普通符号从不转义,也无需转义
为什么用 preg_replace 匹配用户输入时 / 总出错
典型场景:用户搜 foo/bar,你想用 preg_replace 高亮它,写成 "/".preg_quote($user_input)."/" —— 这里 / 是分隔符,但 preg_quote($user_input) 并未转义它,导致正则语法崩溃。
根本原因:你没传 $delimiter 参数。PHP 不知道你打算用什么做分隔符,所以不会动 /。
- 正确写法是
"/".preg_quote($user_input, "/")."/" - 如果换用
#当分隔符,就得写"#".preg_quote($user_input, "#")."#" - 不传
$delimiter时,preg_quote对/视而不见,这不是 bug,是设计如此
preg_quote 不能解决的三类常见“伪特殊字符”
有些符号看着像元字符,实际在正则里是否特殊,取决于上下文。而 preg_quote 无脑转义,有时反而坏事。
-
-:只在字符类内部(如[a-z])作范围连接符;单独出现或在字符类开头/结尾就是字面量。但preg_quote**不转义它** → 若你手动拼[a-z]模式,得自己确保-放对位置,别指望preg_quote帮你兜底 -
^:在字符类开头([^abc])表示取反,在行首(^abc)表示锚点;preg_quote会转义它,但如果你本意就是要用它当锚点,转义后就失效了 → 所以preg_quote只适合用于“纯文本匹配”,不适合构建含逻辑的混合模式 -
$:同理,只在行尾起锚点作用;preg_quote一律转义,若你本想用$表示“行尾”,就不能直接套用
PHP 8.0 下容易踩的兼容性细节
PHP 8.0 没改 preg_quote 行为,但有几个隐性变化影响判断:
- 空字符串
""传给preg_quote返回空字符串,没问题;但若$str是null,PHP 8.0 会报TypeError(之前是静默转成空串)→ 务必先is_string($str)校验 -
$delimiter参数现在严格要求是单字符字符串;传"//"或""会触发ValueError - 二进制安全依然保留,但如果你处理的是 UTF-8 字符串且含 emoji,
preg_quote转义后长度可能突增(因多字节字符本身不被转义,但其周围的标点会被),注意后续strlenvsmb_strlen混用问题
最常被忽略的点:你总想着“哪些要转”,却忘了问一句——这个字符串是不是真该喂给正则?如果只是做字面量替换,str_replace 更快更安全,preg_quote 是为正则服务的,不是万能字符串清洗工具。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











