Java 非捕获正则表达式组提供 "null"捕获

标签 java regex regex-group

我有一个带有 (?:) 格式的非捕获组的 java 正则表达式,我无法理解为什么它为非捕获组提供“null”匹配。

如果我将下面的正则表达式缩短为“@te(st)(?:aa)?”使用相同的 ?: 非捕获组,它给出了我认为的预期行为,仅匹配 1 组和完整匹配。

请参阅下面的正则表达式:

package com.company;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) {
        final String regex = "@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$";
        final String string = "    /**\n     * @test     TestGroup\n     */\n";

        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            for (int i = 1; i <= matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }
    }
}

结果:

Full match: @test     TestGroup
Group 1: TestGroup
Group 2: null
Group 3: null

“@te(st)(?:aa)?”的结果使用相同的代码:

Full match: @test
Group 1: st

第一个将非捕获组匹配为 null 的正则表达式是什么?

最佳答案

回答

这是问题中的正则表达式模式:

"@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$"

此正则表达式模式具有三个捕获组:

  1. ([:.\\w\\\\x7f-\\xff]+)
  2. (\\S*)
  3. (\\S*)

因此,您的第一个示例未将非捕获组匹配为 null。相反,正如预期的那样,它将最后两个捕获组匹配为 null

匹配所有捕获组的另一个示例

如果我们将示例字符串更改为可以匹配模式中所有三个捕获组的字符串,我们将看到三个匹配项。例如:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) {
        final String regex = "@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$";
        final String string = "foo @test : bar baz\n";
        // final String string = "    /**\n     * @test     TestGroup\n     */\n";

        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            for (int i = 1; i <= matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }
    }
}

上述代码的输出为:

Full match: @test : bar baz

Group 1: :
Group 2: bar
Group 3: baz

下面是其他语言中的更多示例,表明这种行为在不同实现中或多或少是相同的。

Python 示例

import re

regex = re.compile('@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$', re.MULTILINE)
s1 = '    /**\n     * @test     TestGroup\n     */\n'
s2 = 'foo @test : bar baz';

match = re.search(regex, s1)
for i in range(regex.groups + 1):
    print('Group {}: {}'.format(i, match.group(i)))
print()

match = re.search(regex, s2)
for i in range(regex.groups + 1):
    print('Group {}: {}'.format(i, match.group(i)))

输出为:

Group 0: @test     TestGroup
Group 1: TestGroup
Group 2: None
Group 3: None

Group 0: @test : bar baz
Group 1: :
Group 2: bar
Group 3: baz

第二个匹配表明非捕获组内的捕获组确实匹配。与 Python 唯一不同的是,不匹配的组不会出现在第一个示例的输出中。

JavaScript 示例

var regex = new RegExp('@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$', 'm')
var s1 = '    /**\n     * @test     TestGroup\n     */\n'
var s2 = 'foo @test : bar baz';
var i

var result = regex.exec(s1)
for (i = 0; i < result.length; i++) {
    console.log('result[' + i + '] :', result[i])
}
console.log()

var result = regex.exec(s2)
for (i = 0; i < result.length; i++) {
    console.log('result[' + i + '] :', result[i])
}

输出为:

result[0] : @test     TestGroup
result[1] : TestGroup
result[2] : undefined
result[3] : undefined

result[0] : @test : bar baz
result[1] : :
result[2] : bar
result[3] : baz

PHP 示例

<?php
$regex = "/@test\\s+([:.\\w\\\\x7f-\\xff]+)(?:[\\t ]+(\\S*))?(?:[\\t ]+(\\S*))?\\s*$/m";
$s1 = "    /**\n     * @test     TestGroup\n     */\n";
$s2 = "foo @test : bar baz";

preg_match($regex, $s1, $matches);
for ($i = 0; $i < count($matches); $i++) {
    echo "Match $i: $matches[$i]\n";
}
echo "\n";

preg_match($regex, $s2, $matches);
for ($i = 0; $i < count($matches); $i++) {
    echo "Match $i: $matches[$i]\n";
}
?>

输出为:

Match 0: @test     TestGroup
Match 1: TestGroup

Match 0: @test : bar baz
Match 1: :
Match 2: bar
Match 3: baz

关于Java 非捕获正则表达式组提供 "null"捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50653314/

相关文章:

java - WAR 文件太大

ruby - 在 Ruby gsub 中使用正则表达式全局变量

ruby - 我如何使用 gsub 将正则表达式 ruby​​ 替换为第 10 组?

html - 选择包含 HTML 类的整行的正则表达式

javascript - 用于检测包含 URL 或文件扩展名的字符串的正则表达式

java - 如何在java中只找到精确的模式匹配?

停在一行的正则表达式

JAVA获取线程中可运行对象

java - 如何在maven中创建多模块项目的汇编

java - 尽管放置正确,但找不到 jSTL