'aaa'.match(/a+/)
匹配到的是a
还是aaa
呢?
结论
贪婪模式(一直查到最多)
默认即贪婪
非贪婪模式(查到第一个即停止)
在通配符如 * . + 后面跟个?
如 a+? .*?
问题
如要删除JS中的 `/* .. */ 块级注释
使用如下正则表达式会有问题
\/\*[\s\S]*\*\/
原因
上述表达式,匹配 /* COMMENT HERE */
是没有问题
但如果是有多个块级注释,如
/* COMMENT 1 */
CODE HERE 1
/* COMMENT 2 */
CODE HERE 2
就会只剩下下面的了。
CODE HERE 2
原因是其中的 [\s\S]*
是贪婪模式的查找,所以把从第一个 /*
到最后一个 */
中间的东西全部都匹配到了。
解决
要解决这个问题,我们希望的规则其实是这样的。
- 从左往右开始查找
- 从第一个遇到的
/*
开始,向右查找 - 当遇到第一个
*/
时,则查找停止,匹配其中的内容
所以核心问题在于,“遇到第一个 */
时,则查找停止”。
而 *
的含义是:匹配前面的子表达式任意次。例如,zo*
能匹配 z
,也能匹配zo
以及zoo
。
其实在正则表达式中,为了解决这个问题,引入了 贪婪模式 与 非贪婪模式的概念。
默认都是贪婪模式,非贪婪模式可以通过在诸如 *
+
等符号后面添加 ?
启用,解释如下。
- 当该字符紧跟在任何一个其他限制符(
*
,+
,?
,{n}
,{n,}
,{n,m}
)后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串oooo
,o+?
将匹配单个o
,而o+
将匹配所有o
。
所以,对于一开始移除块注释的场景,用下面的正则表达式就好了。
\/\*[\s\S]*?\*\/
(正文完)