1

我正在尝试开发一个正则表达式来查找字符串中的一系列标签。例如,我可以有标签(NP .*)至少一次(可以是多次),后跟一个标点符号(在本例中为 a ./.)。如果在 de(NP)和 the之间有另一个标签./.(如下例中的 VP),则 Matcher 一定找不到任何东西。问题是,即使我在之后使用问号,.*它也会继续寻找)使表达式与字符串中的某些内容匹配的 a。这是我的方法:

public void myMethod() {
    String input = "(NP first tag) (VP second tag) ./.";
    String regex = "(\\(NP .*?\\)( )?)+" + "\\./\\.";

    Pattern pattern = Pattern.compile("(" + regex + ")");
    Matcher matcher = pattern.matcher(input);

    if (matcher.find()) {
        System.out.println("<S "+matcher.group(0)+">");
    } else {
        System.out.println("sem grupos.");
    }
}

该方法仍将匹配正则表达式,但不应该。我需要它来告诉我没有找到组,因为“VP”标签不应该在那里。我相信这个问题依赖于 Java 中 Regex 采用的贪婪策略。它试图找到一些符合正则表达式描述的模式的字符组合。我不知道如何重写这个表达式。

有什么帮助吗?

编辑:

1)我注意到我的问题有点令人困惑,所以我对示例进行了一些更改以使其更清楚。

2)谢谢安摩尔。我同意我使用了比必要更多的组,但这是因为像+. 我试图切断不必要的群体。.*?你用 a替换的简单想法[^)]*?也很棒!我唯一调整的是)使用[^\\)]*?. 下面我展示了最终使用的 REGEX。

String regex = "(\\(NP [^\\)]*?\\) ?)+\\./\\.";

非常感谢!:)

4

1 回答 1

1

((\(NP .*?\)( )?)+\./\.)是编译的模式。

简化:

\(NP .*?\) ?+\./\.删除未使用的捕获组。

现在,让我们看看您拥有的示例字符串:

(NP first tag) (VP second tag) ./..*?比赛first tag) (VP second tag
(NP first tag) (VP second tag) (MISC tag that must not be catch) ./..*?匹配first tag) (VP second tag) (MISC tag that must not be catch

为什么?我的意思是,它不是贪婪的,对吧?没错,但是...

.*?\)开始匹配first tag),你想要什么。但是,正则表达式的其余部分未能匹配,正则表达式引擎将其作为可能的答案抛出并继续查找。

如果您在 (NP (tag)) 之类的标签中没有标签,则可以更改模式:\(NP [^)]*?\)

要匹配您在问题中描述的字符串:\(NP [^)]*?\) ?\(VP [^)]*?\) \./\.

随着 Java 转义,它变成\\(NP [^)]*?\\) ?\\(VP [^)]*?\\) \./\..

为了进一步阅读,有一个很棒的Stack Overflow 问题,涵盖了更多关于此的理论和实践。

于 2012-11-07T05:42:40.787 回答