2

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

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

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

4

5 回答 5

4

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

/(ab|cd|ef)/

这也需要使用()括号。但这些括号也充当捕获组。也许您真的不想捕获这些字符序列,只需检查它们的存在,这就是非捕获组发挥作用的地方:

/(?:ab|cd|ef)/
于 2012-11-17T14:44:09.603 回答
3

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

abc(foo|bar)def

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

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

abc(?:foo|bar)def
于 2012-11-17T14:45:46.527 回答
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"

这只会用它自己替换匹配......但你可以用它来创造。

希望这可以帮助。

于 2013-11-23T09:20:46.317 回答
1

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

你想要_____吗

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

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

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

于 2012-11-17T14:55:18.443 回答
1

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

考虑这个文本: 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上尝试一下,您可以看到您的捕获组在哪里

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

于 2012-11-17T15:24:25.063 回答