我知道/?表示/是可选的。所以“玩具?”将匹配玩具和玩具。我的理解是,如果我把它变得懒惰并使用“玩具??”我将匹配玩具和玩具,并总是返回玩具。所以,快速测试:
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”,它仍然匹配toys2和toy2。在这两种情况下,它都会返回整个字符串而不删除s。搜索“玩具?2”和“玩具?? 2”之间是否有任何功能差异。
我问的原因是因为我找到了如下例子:
private final static Pattern TEST_PATTERN = Pattern.compile("</??tag(\\s+?.*?)??>", Pattern.CASE_INSENSITIVE);
虽然我看不出使用的明显理由?而不是?,我想也许原作者(我不认识的人)可能知道我不知道的事情,我期待后者。
答案 0 :(得分:16)
??
是懒惰的,而?
是贪婪的。
给定(pattern)??
,它将首先测试空字符串,然后如果模式的其余部分不匹配,它将测试pattern
。
相反,(pattern)?
将先测试pattern
,然后测试返回的空字符串。
现在,将正则表达式更改为“toys ?? 2”,它仍然匹配toys2和toy2。在这两种情况下,它都会返回整个字符串而不删除s。搜索“玩具?2”和“玩具?? 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
靠近任何地方时,引擎可能会因>
而进行一些昂贵的回溯尝试。