正则中的()和?:

116 阅读1分钟

大佬的demo,可以靠动态切换class改变盒子的形态

webkit.org/blog-files/…

其中有一句正则:

var regExp = new RegExp('(?:^|\\s+)' + inClassName + '(?:\\s+|$)');

很明显用来匹配class中是否包含某个属性名的。用浅薄的正则知识仔细分析:

(开始位置有零次或一次的冒号 || 一个或多个\s) + 传参 + (零次或一次的冒号 || 一个或多个\s) 结尾要冒号做什么??

删除了第二个括号里的后,控制台输出报错:/(?:^|\s+)className(?\s+|$)/: Invalid group连同?一并删除后,功能恢复正常。

查询后发现 ?:()组合使用是非捕获分组的意思。

  • ()表示捕获分组,()会把每个分组里的匹配的值保存起来,使用$n(n是一个数字,表示第n个捕获组的内容)
  • (?:)表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来。

引自blog.csdn.net/csm0912/art…

所以该正则基本等同于var regExp = new RegExp('(^|\\s+)' + inClassName + '(\\s+|$)');

开头和结尾有一个以上\s的className,或者className 只是不保存捕获组的结果。

问题是*是0或多次为什么不直接使用呢?于是改成这样

var regExp = new RegExp('(?:^\\s*)' + inClassName + '(?:\\s*$)');

失效了,F12查看元素,发现删除正则并没有匹配到。

经过一番尝试,把*放到捕获组外,整组重复0次或多次

var regExp = new RegExp('(?:^\\s)*' + inClassName + '(?:\\s$)*');

成功!

那么|\\s+\\s*区别在哪里呢,于是用\\|s*尝试,成功。

结论:()内只有一个时,特殊字符要写在括号外才生效。

把生效的两个正则表达式再记录一遍:

var regExp = new RegExp('(?:^|\\s+)' + inClassName + '(?:\\s+|$)');
var regExp = new RegExp('(?:^\\s)*' + inClassName + '(?:\\s$)*');

xian.png