捕获和非捕获模式有什么区别?

时间:2012-11-17 14:39:50

标签: java regex pattern-matching

Pattern类中,它表示有两种类型的正则表达式:捕获非捕获,但我不明白其中的区别。

http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#special

他们有什么不同?我何时必须使用每一个?有什么例子吗?

5 个答案:

答案 0 :(得分:3)

考虑一种模式,您需要在一个位置检查各种事物,例如一堆不同的两个字符模式。通常使用|交替运算符:

/(ab|cd|ef)/

也需要使用()括号。但这些括号也可作为捕获组。也许你真的不想捕获那些char序列,只是检查它们的存在,这是非捕获组发挥作用的地方:

/(?:ab|cd|ef)/

答案 1 :(得分:2)

您可能希望分组表达式独立于捕获某些内容。例如:

abc(foo|bar)def

如果您想匹配“abdfoodef”或“abcbardef”,但没有其他变体,这是最简单的表达式。您必须使用()将两个表达式分组才能使用|。但这也意味着(foo|bar)是第一个捕获组。

如果您不想要或不需要捕获,请将其写为非捕获组

abc(?:foo|bar)def

答案 2 :(得分:1)

捕获组允许您重用部分正则表达式匹配。您可以在正则表达式中重用它,或者之后例如在替换语句中重用它:

考虑这个文本:1a2b3cdef7g9h 和这个正则表达式:([0-9] *)([a-z] *) 有两个捕获组,第一个捕获数字序列,第二个捕获数组序列。

因此,您可以使用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上试用 在屏幕底部,您可以看到捕获组的位置

请参阅:http://www.regular-expressions.info/brackets.html

答案 3 :(得分:1)

我想应该提一下,你也可以像这样创建命名捕获组:

(?<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"

哪个会替换自己的匹配......但你可以用它来创造。

希望这有帮助。

答案 4 :(得分:0)

捕获/不捕获不是指整个正则表达式,而是指组,即带括号的表达式

你想

吗?
  • 使用反向引用
  • 检索整场比赛的特定部分? (或多个)

如果,那么您将需要捕获组。

如果不是,那么您正在使用括号进行优先控制,并且可以使该组无法捕获。