为什么这个正则表达式在 PHP 中可以正常工作,而在 Java 中却不能正常工作


Why does this regular expression work correctly in PHP but not in Java?

所以我有这个正则表达式

 ^<(.*?)>

这应该与第一个开始标签的内容匹配。然而,虽然这在PHP中有效,但在java中,它匹配了第一个<和最后一个>之间的所有内容。

例如,当它在此上运行时:

<tag1 attr1="val1"><tag2></tag2></tag1>

PHP 匹配:

 tag1 attr1="val1"

而爪哇匹配

tag1 attr1="val1"><tag2></tag2></tag1
String s1="<tag1 attr1='"val1'"><tag2></tag2></tag1>";
Pattern p = Pattern.compile("^<(.*?)>");
Matcher m = p.matcher(s1);
while(m.find()) {
    System.out.println(m.group(1));
}

这是我测试的代码,它返回tag1 attr1="val1" .

然后,在评论中,你说你使用的是matches方法:这就是区别。

虽然 find 方法检查字符串中与正则表达式匹配的任何部分,但 matches 方法要求整个字符串与给定正则表达式匹配。

因此,在您的示例中:

while(m.find()) {
    System.out.println(m.group(1)); //will print   tag1 attr1="val1"
}
if (m.matches()) { //will evaluate the regex as ^<(.*?)>$
    System.out.println(m.group(1)); //will print    tag1 attr1="val1"><tag2></tag2></tag1
}

我第一次没有发现的是你明确使用了非贪婪重复(*?)。

但我的原始观点仍然成立:

  • 在这方面,PHP 和 Java 正则表达式的语义没有区别。

  • 使用 Java find 与 Java matches 不会改变正则表达式的语义。 具体来说,它不会将非贪婪转变为贪婪,反之亦然。 (正如您在评论中假设的那样。

find成功(多次)而matches没有成功的原因完全取决于matches必须匹配整个字符串的事实。