我知道 /?表示/是可选的。那么“玩具?”将匹配玩具和玩具。我的理解是,如果我变得懒惰并使用“玩具?”我将玩具与玩具都匹配,并且总是返回玩具。因此,快速测试:
private final static Pattern TEST_PATTERN = Pattern.compile("toys??", Pattern.CASE_INSENSITIVE);
public static void main(String[] args) {
for(String arg : args) {
Matcher m = TEST_PATTERN.matcher(arg);
System.out.print("Arg: " + arg);
boolean b = false;
while (m.find()) {
System.out.print(" {");
for (int i=0; i<=m.groupCount(); ++i) {
System.out.print("[" + m.group(i) + "]");
}
System.out.print("}");
}
System.out.println();
}
}
是的,看起来像预期的那样
java -cp .. regextest.RegExTest toy toys
Arg: toy {[toy]}
Arg: toys {[toy]}
现在,将正则表达式更改为“ toys ?? 2”,它仍然匹配toy2和toy2。在这两种情况下,它都返回完整的字符串,而不删除。搜索“ toys?2”和“ toys ?? 2”之间在功能上有什么区别。
我问的原因是因为我找到了一个类似以下示例:
private final static Pattern TEST_PATTERN = Pattern.compile("</??tag(\\s+?.*?)??>", Pattern.CASE_INSENSITIVE);
尽管我没有明显的理由使用??而不是?,我认为也许是原作者(我不认识的作者)可能会知道我不知道的东西,我希望以后会知道。
最佳答案
??
是懒惰的,而?
是贪婪的。
给定(pattern)??
,它将首先测试空字符串,然后如果模式的其余部分不匹配,则将测试pattern
。
相反,(pattern)?
将首先测试pattern
,然后将测试回溯中的空字符串。
现在,将正则表达式更改为“ toys ?? 2”,它仍然匹配toy2和toy2。在这两种情况下,它都返回完整的字符串,而不删除。搜索“ toys?2”和“ toys ?? 2”之间在功能上有什么区别。
区别在于搜索顺序:"toys?2"
搜索toys2
,然后搜索toy2
"toys??2"
搜索toy2
,然后搜索toys2
但是对于这两种模式,无论输入字符串如何,结果都将相同,因为续集2
(在s?
或s??
之后)必须匹配。
至于您发现的模式:
Pattern.compile("</??tag(\\s+?.*?)??>", Pattern.CASE_INSENSITIVE)
可以将两个
??
都更改为?
,而不会影响结果:/
和t
(在tag
中)是互斥的。您可以彼此匹配。>
和\s
也是互斥的。 \s+?
中的至少1对于此结论很重要:否则结果可能会有所不同。作者可能对此进行了微优化。他可能认为打开标签必须存在,而关闭标签可能会被遗忘,并且没有属性/随机空间的打开/关闭标签比带有某些标签的打开/关闭标签的出现频率更高。
顺便说一句,当输入有
\\s+?.*?
且后面有很多空格且附近没有<tag
时,由于>
,引擎可能会进行一些昂贵的回溯尝试。