在Pattern
课堂上它说有两种类型的正则表达式:捕获和非捕获,但我不明白其中的区别。
http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#special
它们有何不同?我什么时候必须使用每一个?有什么例子吗?
在Pattern
课堂上它说有两种类型的正则表达式:捕获和非捕获,但我不明白其中的区别。
http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#special
它们有何不同?我什么时候必须使用每一个?有什么例子吗?
考虑一种模式,您需要在单个位置检查各种事物,例如一堆不同的两个字符模式。通常您使用|
交替运算符:
/(ab|cd|ef)/
这也需要使用()
括号。但这些括号也充当捕获组。也许您真的不想捕获这些字符序列,只需检查它们的存在,这就是非捕获组发挥作用的地方:
/(?:ab|cd|ef)/
您可能希望独立于捕获某些内容的表达式对表达式进行分组。例如:
abc(foo|bar)def
如果您想匹配“abdfoodef”或“abcbardef”,但不匹配其他变体,这是最简单的表达式。您必须使用()
对两个表达式进行分组才能使用|
. 但这也意味着这(foo|bar)
是第一个捕获组。
如果您不想要或不需要捕获,请将其写为非捕获组:
abc(?:foo|bar)def
只是想我应该提一下,您还可以像这样创建命名捕获组:
(?<telephone>(?:\(\d{2}\)\s\d{4}\s\d{4}))
这将匹配一个电话号码,如(02) 9502 5697
然后,您可以将其用作反向引用,如下所示:
"s/(?<telephone>(?:\(\d{2}\)\s\d{4}\s\d{4}))/\k<telephone>/g"
这只会用它自己替换匹配......但你可以用它来创造。
希望这可以帮助。
捕获/非捕获不是指整个正则表达式,而是指组,即带括号的表达式。
你想要_____吗
如果是,那么您将需要捕获组。
如果不是,那么您正在使用括号进行优先级控制,并且可以使组不被捕获。
捕获组允许您重用部分正则表达式匹配。您可以在正则表达式中重用它,或者之后在替换语句中重用它:
考虑这个文本: 1a2b3cdef7g9h 和这个正则表达式: ([0-9]*)([az]*) 有两个捕获组,第一个捕获数字序列,第二个捕获字母序列。
因此,您可以使用 replaceAll 语句使用第一个捕获组 ($1) 保留数字,或使用第二个捕获组 ($2) 保留字母。
// next line outputs : 12379
System.out.println("1a2b3cdef7g9h".replaceAll("([0-9]*)([a-z]*)", "$1"));
// next line outputs : abcdefgh
System.out.println("1a2b3cdef7g9h".replaceAll("([0-9]*)([a-z]*)", "$2"));
但是当您使用非捕获组时(例如通过添加 ?: 它不会捕获,并且有时很有用。例如:
// next line outputs : abcdefgh
// ([a-z]*) becomes the first capturing group because (?:[0-9]*) is a non-capturing group
System.out.println("1a2b3cdef7g9h".replaceAll("(?:[0-9]*)([a-z]*)", "$1"));
在屏幕底部的http://gskinner.com/RegExr上尝试一下,您可以看到您的捕获组在哪里