使用 Java 匹配正则表达式组

Matching regex groups with Java

我正在尝试通过使用组来使用正则表达式拆分一行,但它没有像我预期的那样工作。
我想匹配例如这一行:

例如。 #1:temp name(this is the data)

还有这个:

例如。 #2:temp name()

我使用了这个正则表达式:

[\s]*temp[\s]+[\s]*([A-Za-z]+)[\s]*[(]\s*(.*)+[)]\s*[{]\s*

这意味着:抓取任何以 temp 开头的内容,然后将 "name" 放入第 1 组,然后抓取括号内的任何内容并将其放入第 2 组。

但是,第 2 组始终为空。

这是我获取数据的代码:

Pattern PATTERN = Pattern.compile("[\s]*temp[\s]+[\s]*([A-Za-z]+)[\s]*[(]\s*(.*)+[)]\s*");

Matcher m = PATTERN.matcher("temp name(this is the data)");
m.matches();
String name = m.group(1);
String data = m.group(2); // always empty

我做错了什么?

您的模式不匹配,因为它需要在末尾有一个左花括号,但您的输入没有。

忽略那个小问题,主要问题是捕获组 (.*)+ 之后的小 +。 plus 需要一个 或更多 .* 匹配,返回的组是 最后一个 个匹配。术语 .* 是贪婪的,所以它会消耗括号内的所有内容。再次匹配 的唯一方法是消耗 nothing。所以组 2 的 last 匹配是空白的。

要修复它,请删除第 2 组后的 +

Pattern PATTERN = Pattern.compile("\s*temp\s+([A-Za-z]+)\s*[(]\s*(.*)[)]\s*");

另请注意我如何从您的正则表达式中删除其他不必要的字符,例如单字符字符 类 - 即 [\s]\s 相同。 \s+\s*\s+ 相同,因为 + 是贪心的。

我还删除了尾随大括号,如果您的输入数据确实有它,您可以恢复它(您的问题显示 "temp name(this is the data)" 的输入,它没有尾随大括号)。

[\s] 等同于 \s

[\s]+[\s]* 等同于 \s+

[(] 等同于 \([)][}] 相同)

这将使您的正则表达式为:

\s*temp\s+([A-Za-z]+)\s*\(\s*(.*)+\)\s*\{\s*

假设您实际上想要匹配 temp name(...) {(您的正则表达式正在寻找 {,而在您的问题中您没有指定):

(.*)+ 是你的问题。你说的是:"Match any number (including 0) chatacters and put them in a capture group, repeat that at least once"。

正则表达式默认是贪婪的(=它们消耗尽可能多的),所以捕获组将首先包含两个括号内的所有内容,然后 + 将再次尝试匹配整个组,并且将它与 "" (空字符串)匹配,因为它满足捕获组的模式。这将使您的捕获组变空。

你想要的是 \s*temp\s+([A-Za-z]+)\s*\(\s*(.*)\)\s*\{\s*

你的正则表达式应该是这样的:

Pattern pattern = Pattern.compile("\s*temp\s+([A-Za-z]+)\s*[(]\s*(.*)[)]\s*");

您有 (.*)+,这意味着 .* 的一个或多个匹配项。这导致什么都没有被捕获。

测试:

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

public class Example {

    public static void main(String[] args) {

        Pattern pattern = Pattern.compile("\s*temp\s+([A-Za-z]+)\s*[(]\s*(.*)[)]\s*");

        Matcher m = pattern.matcher("temp name(this is the data)");
        if(m.matches()) {
            System.out.println(m.group(1));
            System.out.println(m.group(2));
        }
    }
}

输出:

name
this is the data

你得到空组的原因是每次你在 () 之间放置一些东西时你都会创建多个捕获组,即使它是嵌套的。

要创建一个不捕获的组,您可以使用 ? 将其指定为非捕获组:例如,(?:sometest(this is the value we want)) 将 return 仅一组,而 (sometest(this is the value we want)) 将return 2组。

对于您的特定正则表达式,我对其进行了改进和简化,因为您拥有不需要的捕获组。

简单的解决方案:

\s*temp\s+([A-Za-z]+)\s*\(\s*(.*)\)\s*\{\s*

给定输入:

Ex. #1: temp name(this is the data) {
Ex. #2: temp name() {

= name, = data

请注意您的正则表达式包含尾随花括号这一事实。您可以修改正则表达式以在没有它的情况下进行匹配,结果将是:

\s*temp\s+([A-Za-z]+)\s*\(\s*(.*)\)\s*

https://regex101.com/r/tD0tO0/1