正则表达式-分隔符示例

原创
2018/05/15 15:19
阅读数 5.2K

说明

文本中经常需要匹配分隔符内的内容,像程序中的注释以/*开头,*/结尾;双引号""内的字符等,我们今天以这个例子来一步步的构建这个正则表达式

我们以""来作示例

一 凭直觉

可以简单写为"[^"]*"
对于处理"haha haha"这种的足够了, 不过如果有转义斜线\怎么处理?就是对于"\"This is Tom\" he said",我们只会先匹配到\,但在语义上与我们要匹配的不符合

二 环视

可以采用环视,\"认为是正常文本,这样表达式写为"([^"]|(?=\\)")*"

三 转义字符

对于上面的表达式,我们如果匹配 "hello there \\" else "hello world" 按上面例子匹配到else后的",问题是\是被转义的,匹配到这里是不对的。 考虑到\\是成对出现的,\后面的字符都是被转义的,具体是什么其实无所谓, 我们可以以反斜线后面跟一个点号来匹配这样的内容,写为"(\\.|[^"])*"

四 不匹配的字符串

我们再来构造一个不应该匹配的串: "hello there \2\3" and world 按照三种的正则式会匹配出来hello there \2\3\, 在\\.匹配后,到最后没有找到后面的",所以会回溯到\"\匹配[^"], "匹配最后的" 从这我们看到在后面中括号里面也不应该包括反斜线,把它去掉,改写为:"((\\.)|[^\\"])*"

五 效率问题

这个式子就可以了,不过效率不够好,因为反斜线转义的字符在前面,但是普通字符出现的频率比反斜线转义的字符要高,引擎在传动之后发现不匹配就需要回溯,造成了很多的浪费,我们来换一下位置变为:"([^\\"]|(\\.))*"

六 占有优先量词和固化分组

如果我们使用占有优先量词和固化分组更好一点,这样在三中出现的问题就没有问题了,因为占有优先量词在回溯时不会交还字符,而是直接报错. "(\\.|[^"])*+" \\.匹配的字符不会交还,就不会出问题 "((?>\\.)|[^"])*" "(?>(\\.|[^"])*)" 这两种应该都可以

七 总结

总结两点 1:要深刻理解回溯,多选结构匹配出来的结构可能并不是我们想要的。 2:多写注释,后面自己都忘了当时为什么要写这么复杂了,其实写完再看四或六中的表达式对于当时是怎么思考的已经忘的差不多了,但是文档却会让我们的思考变得有迹可循。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部