preg_match函数中正则表达式表现异常的原因咨询
问题分析与解决方案
第一个正则匹配失败的原因
PHP的preg_match默认使用PCRE(Perl兼容正则表达式)的非Unicode模式,在这个模式下,\p{L}这类Unicode属性规则根本无法正确识别——它只会匹配ASCII范围内的字母,像Ǻ、α、ᗩ这类非拉丁Unicode字母会被判定为不符合规则的字符,直接导致整个匹配失败。
而你用的在线测试器大概率默认开启了Unicode支持,所以能正常匹配这些字符。解决这个问题很简单,只需要在正则表达式末尾加上/u修饰符,开启PCRE的Unicode模式,让\p{L}能正确匹配所有Unicode字母:
$text = 'ǺǻαάǠẮắẰằẳẴẵĪäÅÀÁÂåãâàáÃᗩ'; // 加上/u修饰符开启Unicode模式 if(preg_match("/^([\p{L}0-9~!@#$%^&*_\-+='|{}\(\)\[\]:;\"<>,.?\/\\\s])+$/iu", $text)){ echo 'success'; } else { echo 'fail'; }
运行这段代码就会输出success了。
第二个正则“几乎匹配所有内容”的原因
你第二个正则去掉了开头的^和结尾的$锚点,preg_match的逻辑是只要字符串中存在任意一段符合正则的内容,就会返回匹配成功,而不是要求整个字符串都完全符合规则。哪怕字符串里混着✪、❀这类你想忽略的符号,只要里面有一个字母或允许的特殊字符,就会匹配成功,所以才会出现“几乎匹配所有内容”的情况。
额外小提示
在字符集[]里,-如果放在开头或结尾(或者转义)才不会被当成范围符号,你这里把\-放在了中间其实是可以的,但如果怕出错,也可以把-移到字符集的最后,这样不用转义也不会有问题,比如:
[\p{L}0-9~!@#$%^&*_+='|{}\(\)\[\]:;"<>,.?\/\\\s-]
内容的提问来源于stack exchange,提问作者Manuel Wulf
相关产品推荐
相关产品推荐

