k8w.io
正则表达式的非贪婪模式
2017-11-20作者:k8w

'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]*是贪婪模式的查找,所以把从第一个 /* 到最后一个 */ 中间的东西全部都匹配到了。

解决

要解决这个问题,我们希望的规则其实是这样的。

  1. 从左往右开始查找
  2. 从第一个遇到的 /* 开始,向右查找
  3. 当遇到第一个 */ 时,则查找停止,匹配其中的内容

所以核心问题在于,“遇到第一个 */ 时,则查找停止”。
* 的含义是:匹配前面的子表达式任意次。例如,zo*能匹配 z,也能匹配zo以及zoo
其实在正则表达式中,为了解决这个问题,引入了 贪婪模式 与 非贪婪模式的概念。
默认都是贪婪模式,非贪婪模式可以通过在诸如 * + 等符号后面添加 ? 启用,解释如下。

  • 当该字符紧跟在任何一个其他限制符(*, +, ?, {n}, {n,}, {n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串ooooo+?将匹配单个o,而o+将匹配所有o

所以,对于一开始移除块注释的场景,用下面的正则表达式就好了。

\/\*[\s\S]*?\*\/
(正文完)
留言(0条)
发表新留言
您的大名:
必填
电子邮箱:
不公开,仅用于向你发送回复
粤ICP备17160324号-3