赞
踩
本文主要采用 POSIX 标准下的扩展正则表达式 (POSIX-extended) 风格, 并使用了一些 POSIX 未定义但比较常用的特性.
不同正则表达式引擎有些微的差异, 常用的正则表达式引擎罗列如下:
Perl, PCRE, PHP, .NET, Java, JavaScript, XRegExp, VBScript, Python, Ruby, Delphi, R, Tcl, POSIX 等. (参见 https://www.regular-expressions.info/tutorial.html)
基础概念此处不再赘述, 下面讲一些后面用到的 POSIX 标准中可能未定义的特性.
参见 https://www.regular-expressions.info/lookaround.html)
Pattern1(?=Pattern2)
Pattern1(?!Pattern2)
参见 https://www.regular-expressions.info/brackets.html
?: (Non-Capturing Groups)
(?:Pattern)
禁用小括号所表示的分组的默认捕获功能, 若不禁用, 则正则表达式引擎会将括号内的 Pattern 所匹配的字符串暂存起来, 带来不必要的开销.
分组的作用与本文无关, 故不再赘述. 感兴趣者可参阅本节链接.
难点在于正则表达式是贪婪的 (是满足某个模式的最大匹配), 然而C语言注释是以 /*
开始, 遇到第一个 */
结束, 是最小匹配, 因而下面的写法是错误的
\/\*(.|\n)*\*\/ if . exclude newline
\/\*.*\*\/ if . include newline
若有多个块注释, 则会从第一个块注释的开始匹配到最后一个块注释的结尾.
因此我们需要使用正则表达式使得模式中间不得出现 */
.
\/\*(?:\*(?!\/)|[^\*])*\*\/
这个方案比较直观, 必须使用前向匹配, 了解前向匹配以后就很容易理解, 然而一些正则表达式引擎可能不支持前向匹配.
该方案参考了 stackoverflow 上的回答.
\/\*(?:[^\*]|\*+[^\/\*])*\*+\/
这个方案就没那么直观了.
前面的 /*
很好理解, 结尾的模式则是 */
前面可以有若干(
≥
0
\ge0
≥0)个 *
.
中间的模式为 (a) 若干(
≥
1
\ge1
≥1)个 *
+ 非 /
亦非 *
的结尾; (b) 非 *
的字符 两者的随机重复组合, 可以看到, 由于 (a) (b) 均不以 *
结尾, 且 (a) (b) 内不会出现 */
, 故中间的模式不可能出现 */
. 此外, 正是由于 (a) (b) 均不以 *
结尾, 故结尾的模式要补上若干个 *
.
注 此处使用 ?:
是为了性能优化, 对于不支持该特性的正则表达式直接去掉即可.
该方案参考了 stackexchange 上的回答.
推荐一个测试网站, 体验极佳
https://www.regextester.com/93553
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。