正则的定界符并非只可以用 / 号

  • 作者:KK

  • 发表日期:2019.08.21


  • 要点速读:#http://xxx\.com#/http:\/\/xxx\.com/这两个正则的匹配效果是一模一样的,而且前者更简洁。

多年来偶尔上网查一些正则时,看到大部分文章的正则并没有以最简洁的方式写出来,其中一个啰嗦的地方就是这样的:preg_match('/http:\/\/xxx\.com/', $var),其实这个代码可以简化成preg_match('#http://xxx\.com#', $var),个人觉得这样看起来很直观,少了一些黑底符的干扰,问题的本质就是:所书写的正则表达式到底用了什么定界符(左右两边的那个符号)

我认为很多人的第一习惯就是用/号做定界符的,而作为 Web 开发者在开发过程中要匹配的内容经常都需要匹配里面的/号,由于与定界符产生了冲突,于是内部这些被匹配的内容就需要写成\/使得这个表达式看起来啰嗦复杂。

在PHP里,正则表达式的左右两边都需要用同样的符号,这是原则,并没有限定咱们用哪个符号,所以其实/abc\d+/#abc\d+#~abc\d+~这样都是等效的。

但右边定界符后面倒是可以带其它修饰符,比如preg_match('#abc#i', 'Abc')不区分大小写匹配,而preg_match('#abc#', 'Abc')是按照大小写匹配的,区别就是右边的#这个定界符后面多了个修饰符i,这里并不详细讲修饰符,只是说明定界符的作用和界限而已。

而在官方文档里确实是是优先使用/号作为定界符进行示例的,这样会导致很多开发者第一想法就是跟着用这个。其实官方用那个符号倒是有它的好处,因为在JS里也需要用定界符,如/abc\d+/.test('xabc99]]]')/abc\d+/ig.test('xabc99]]]').号左边的都是一整个正则对象,并且只能用/作为定界符。PHP相关的文章也用相同的符号,可以使得大家在有需要的情况下直接将正则复制到JS代码里跑而不需要什么转换书写,然而这毕竟是很少数的需求,往往搜索JS匹配XXXX的关键词出来都是JS的正则,而且PHP正则里的修饰符也并不完全能套用在JS身上。

认清真相,理智写代码,我提倡在PHP里用#号作为定界符以避免内部出现\/导致表达式啰嗦(不过如果内部有#号要匹配时,则也需要写在\#,只是情况很少,甚至你用~就更少了),其中著名的Yii2这个框架在路则规则匹配时相关的路由代码都是用#号做定界符的。