JAVA 正则表达式 非捕获组(特殊构造)
2825 点击·0 回帖
![]() | ![]() | |
![]() | 在 java api 文档中的正则表达式关于特殊构造(非捕获组)的说明看不懂。例如: (?:X) X,作为非捕获组 (?idmsux-idmsux) Nothing,但是将匹配标志由 on 转为 off (?idmsux-idmsux:X) X,作为带有给定标志 on - off 的非捕获组 (?=X) X,通过零宽度的正 lookahead (?!X) X,通过零宽度的负 lookahead (?<=X) X,通过零宽度的正 lookbehind (?<!X) X,通过零宽度的负 lookbehind (?>X) X,作为独立的非捕获组 这些字都说的很抽象。不懂……。还是搜索下去。找到 火龙果 的解释如下:以 (? 开头,) 结尾的都称为非捕获组,在匹配完成后在内存中不保留匹配到的字符。非捕获组的应用比较复杂,这里只能简单地说一下它们的意思。 1、(?:X) X,作为非捕获组 与捕获组 ( ) 的意思一样也是将其作为一组进行处理,与捕获组的区别在于不捕获匹配的文本,仅仅作为分组。 比如:要匹配 123123 这个,就可以写为 (123)\1 使用反向,这时只能用捕获组,在匹配 123 后会保留在内存中,便于反向,而 (?:123) 在匹配完后则不会保留,区别仅在于此。 2、(?idmsux-idmsux) Nothing,但是将匹配标志i d m s u x on - off 用于标志匹配,比如:表达式 (?i)abc(?-i)def 这时,(?i) 打开不区分大小写开关,abc 匹配不区分大小地进行匹配,(?-i) 关闭标志,恢复不区分大小写,这时的 def 只能匹配 def 3、(?idmsux-idmsux:X) X,作为带有给定标志 i d m s u x on - off 与上面的类似,上面的表达式,可以改写成为:(?i:abc)def,或者 (?i)abc(?-i:def) 4、(?=X) X,通过零宽度的正 lookahead 5、(?!X) X,通过零宽度的负 lookahead (?=X) 表示当前位置(即字符的缝隙)后面允许出现的字符,比如:表示式 a(?=b),在字符串为 ab 时,可能匹配 a,后面的 (?=b) 表示,a 后面的缝隙,可以看作是零宽度。 (?!X) 表示当前位置后面不允许出现的字符 6、(? <=X) X,通过零宽度的正 lookbehind 7、(? <!X) X,通过零宽度的负 lookbehind 这两个与上面两个类似,上面两个是向后看,这个是向前看 8、(?>X) X,作为独立的非捕获组 匹配成功不进行回溯,这个比较复杂,也侵占量词“+”可以通用,比如:\d++ 可以写为 (?>\d+)。 我认为,第1、2、3点比较好理解,4、5、6、7看类懂,还是用示例来说明:从“aacabab”找a,且后面只允许出现b。代码如下: Pattern p = Pattern.compile("a(?=b)"); Matcher m = p.matcher("aacabab"); while(m.find()) { System.out.println(m.group()+", start="+m.start()+", end="+m.end()); } 运行结果: a, start=3, end=4 a, start=5, end=6 个人理解:在(?=b)这个“式”后面允许出现b,且这个“式”不占正则表达式位置(所谓0宽度),lookahead 的意思是b字符的前面,它前面紧接着是a,也就是a后面出现b。 8比较难理解,这个根据 火龙果 推荐的链接找到答案 http://www.regular-expressions.info/atomic.html 其中说的示例:来看 /\b(integer|insert|in)\b/ 匹配 integers 过程,第一个,当integer\b匹配到s时失败,然后字符串(integers)会回溯到i,再接着第二个(insert)去匹配。而把模式写成 /\b(?>integer|insert|in)\b/ 在刚才的第一个匹配失败,字符串(integers)不会回溯了,也不会有第二个去匹配了,所有速度会快一点点。 但是写 (?>X) 这种式子时要注意,是从左到右看的。/\b(?>integer|insert|in)\b/ ,与 /\b(?>in|integer|insert)\b/ 去匹配 insert,结果会不一样,前者可以匹配到,后者不能,什么原因自己分析下。一但匹配失败就会跳过,所以应该长的写在表达式前面. | |
![]() | ![]() |