把前端那段 /^1[3-9][0-9]{9}$/g 直接搬进 PHP,页面立刻报 preg_match(): No ending delimiter / found。前端能跑的写法,到 PHP 里第一步就卡住。
PHP 的正则不是字面量,是字符串。字符串就得有首尾分隔符,还得注意修饰符和返回值,这三处最容易翻车。
分隔符和修饰符
preg_match 第一个参数是字符串,首尾用同一个符号包住,斜杠、井号、波浪号都行。写成 preg_match('/^[a-z]+$/', $name) 才对。
末尾那个 g 是 JS 的全局标志,PHP 没有 g。preg_match 只找第一个,找全部用 preg_match_all。i 忽略大小写,m 让 ^ 和 $ 按行匹配,s 让点号匹配换行,u 按 UTF-8 处理。
匹配中文一定加 u,不加就按字节切,量词会把一个汉字劈成两半,结果时对时错。
三个函数的分工
preg_match 返回 1 表示匹配,0 表示不匹配,false 表示出错。判断用 === 1,别只写 if,出错和没匹配是两回事。preg_match_all 第三个参数接结果数组,第四个参数用 PREG_SET_ORDER 按组排列,处理表格文本时好用。
替换用 preg_replace,切分用 preg_split。这三个够覆盖九成场景,剩下的查手册再写。
转义和常见坑
用户输入拼进正则前先过 preg_quote($kw, '/'),不然句号和星号会被当成元字符,搜「3.5」能把 3a5 也搜出来。内容里本身有斜杠,换个井号当分隔符,比一个个转义省事。
长文本配贪婪的 .* 容易触发回溯上限,pcre.backtrack_limit 默认 1000000,超了 preg_match 返回 false,preg_last_error() 会给 PREG_BACKTRACK_LIMIT_ERROR。把贪婪改成懒惰,或者先截断再匹配。
手机号和邮箱的写法
手机号用 /^1[3-9][0-9]{9}$/,别加多余的空格和横线。邮箱别追求完美正则,先 filter_var($mail, FILTER_VALIDATE_EMAIL),再发验证邮件,能收信才算数。
用户名限制用 /^[A-Za-z0-9_]{6,16}$/,长度按字节算,中文要用 mb_strlen,不然一个汉字算三个字符。
实际排查时,先看分隔符成对没有,再看中文有没有加 u,再确认返回值是不是 === 1。这三步能解决大部分 php正则 不生效的问题。