日期:2014-05-19  浏览次数:20708 次

正则表达式中?:的用法疑惑
用表达式(?:ab)([a-z]*?)(?=df)来匹配77abcddf88,为何会得到:abcd。目的是不包含ab,应该得到cd才是啊。另:改成(?:ab)([a-z]*?)(?:df)为何匹配到abcddf??:与?=有何区别?感觉都是表示以指定字符开始,但不缓存当前括号的内容。

------解决方案--------------------
?:,非捕获组,意思是这个组不自动编号,而不是不捕获这个组,如上面的例子,如果没有?:,那么1捕获组就是ab。
------解决方案--------------------
还是我讲讲吧
(?:ab)([a-z]*?)(?=df)
?: 的确是非捕获组,但其含义是 不会在组中捕获 但会在匹配结果中出现
比如你这个正则,group[1]的值会是 cd
如果(ab)这样 group[1]的值是ab
但这两个匹配的结果是一样的 都是abcd
?=正声明,出现在右边即不被组捕获也不被结果捕获
? <=反向正声明 在左边 其他一样 (另:我自打学正则就没听说只有c#有他)


------解决方案--------------------
这是一个比较抽象的概念,谈到相对位置,前或后,左或右,那就一定要有一个参照物的,这里所说的所在位置的左侧或右侧是对参照物而言的,并不是(? <=Exp)或(?=Exp)本身,我们可以把它所参照的位置理解为一个零宽度的位置或“缝隙”,下面举例说明吧

先从简单的开始,有两个字符串
str1 = "a123b "
str2 = "a123c123b "
有一个正则表达式:(? <=a)\d+(?=b)
这里的\d+是明确的,就是数字,它可以做为参照物,而(? <=a)在“缝隙”处加了一个限定条件,在它的左侧为a,这里的“缝隙”指的就是(? <=a)和\d+之间的“缝隙”,由(?=b)加了一个限定条件,在它的右侧为b,这里的“缝隙”指的就是\d+和(?=b)之间的“缝隙”,用它来匹配str1的结果是匹配成功,而匹配str2的结果是不成功,因为str2两组数字的两侧都不同时满足这两个条件

换成另一个正则表达式:(?=a)\d+(? <=b)
我们根本不用拿任何例子去试,从正则表达式本身就可以断定它匹配不到任何内容,因为它本身就是自相矛盾的,(?=a)附加的条件是在“缝隙”的右侧是a,而很明显这个式子里“缝隙”的右侧一定是数字才能匹配成功,(? <=b)同理

或者把以上的\d+直接写为123可能会更有组于你的理解


再来说下(?=ab)([a-z]*?)(?=df)这个表达式,如果用它来匹配77abcddf88字符串,也是可以匹配成功的,但匹配的结果是abcd,因为(?=ab)要求它所参照的“缝隙”右侧为ab,这里只有77和ab之间的“缝隙”才满足条件,而(?=df)要求它所参照的“缝隙”右侧为df,这里只有cd和df之间的“缝隙”满足要求,所以匹配结果为abcd
而(? <=ab)([a-z]*?)(?=df)这个表达式,(? <=ab)要求缝隙的左侧为ab,这里只有ab和cd之间的“缝隙”满足要求,(?=df)同上,所以匹配结果为cd
------解决方案--------------------
ab(\w+)df
------解决方案--------------------
lxcnn(过客) 正解。
虽然正则用的很多,但对零宽度匹配一直没有很好的掌握,可能是因为这一部分是正则中各种语言差异最大的部分了