为什么捕获组中的标志会删除该组?

时间:2018-08-21 03:06:46

标签: java regex

在以下代码中,(?i:hot)是捕获组。或者至少应该是...它匹配表达式并使用字符。

但是,当我尝试获取组数时,它返回0。

Pattern pattern = Pattern.compile("(?i:hot)");
Matcher matcher = pattern.matcher("hot diggity dog");
while (matcher.find()) {
    int groupCount = matcher.groupCount(); // returns 0
    for (int i = 0; i <= groupCount; i++) {
        System.out.printf("%d. %s%n", i, matcher.group(i));
    }
}

括号会捕获。如您所见,如果我们这样做

matcher.replaceAll("cold")

它将返回“冷眼狗”

我希望(?i:hot)等同于((?i)hot),但事实并非如此。后一种情况是捕获组。

这不是Java RegEx Matcher.groupCount returns 0的重复项,因为在该问题中,确实没有捕获组,因此groupCount正确返回0。但是,在我的情况下,应将其视为捕获组,因为它确实可以执行捕获!

3 个答案:

答案 0 :(得分:5)

它在documentation中:

  

(?idmsux-idmsux: X X ,作为非捕获组,其中idmsux的给定标志为开-关

如果您想要一个捕获组,只需将其包装在另一组括号中即可:

((?i:hot))

答案 1 :(得分:2)

您正在使用?i:。这不是要忽略大小写的提示,而是非捕获组的语法。我发现一个用例是用在正则表达式中间的(?i)来忽略后向引用\1的大小写匹配。以下是使用它的程序的修改版本

Pattern pattern = Pattern.compile("\\b(\\w+)(\\W+(?i:\\1)\\b)+");
Matcher matcher = pattern.matcher("Hello hello");
    while (matcher.find()) {
        int groupCount = matcher.groupCount(); // returns 0
        for (int i = 0; i <= groupCount; i++) {
            System.out.printf("%d. %s%n", i, matcher.group(i));
        }
    }

答案 2 :(得分:1)

TL; DR

  

我希望(?i:hot)等同于((?i)hot),但事实并非如此。后一种情况是捕获组。

一旦看到相同级别的右括号,几乎所有正则表达式引擎都会关闭内联修饰符。因此,除了捕获部分外,以上两个都是等效的。

第一种语法完全是另一回事。

模式修改的跨度

不应该将括号表示为捕获组或非捕获组,但是它们可以为可能捕获或不捕获的使用带来不同的功能。紧跟问号的所有左括号对于正则表达式引擎都有特殊含义:

(?...)

标记i修饰符。可以在正则表达式上下文之外启用修饰符,但是某些正则表达式引擎支持内联修饰符的语法,该语法使您能够在正则表达式本身中启用它们。因此,单词 inline

(?i)test(?-i)
 ^        ^
 E        D

另一方面,还有另一种类似的语法,称为模式修改的跨度(?modifiers:...),它类似于一个非捕获组(?:...)?:之间具有一些修饰符,并将它们仅 应用于所包含的子表达式:

(?i:test)

话虽如此,(?i)test(?-i)(?i:test)相等。该功能应该启用/禁用修饰符。期间。

我们不希望它有更多功能。