我正在尝试开发一个正则表达式来查找字符串中的一系列标记。例如,我可以将标记(NP .*)
至少一次(可以多次),然后是标点符号(在本例中为./.
)。如果de (NP)
和./.
之间有另一个标记(如下例中的VP),则匹配器不能找到任何内容。问题是,即使我在.*
之后使用问号,它也会继续寻找使表达式与字符串中的某些内容匹配的)
。这是我的方法:
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中采用的贪婪策略。它试图找到一些符合正则表达式描述的模式的字符组合。我不知道如何重写这个表达式。
任何帮助?
编辑:
1)我注意到我的问题有点令人困惑,所以我改变了一些例子以使其更清晰。
2)谢谢Aan Moore。我同意我使用的组不是必要的,但这是因为像+
这样的运营商。我试图削减不必要的群体。您将.*?
替换为[^)]*?
的简单想法也很棒!我调整的唯一一件事是我使用)
转义了[^\\)]*?
符号。下面我展示了最终使用的REGEX。
String regex = "(\\(NP [^\\)]*?\\) ?)+\\./\\.";
非常感谢! :)
答案 0 :(得分: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 question涵盖了更多的理论和实践。