正则表达式量词中的混淆?JAVA
为什么我要为下面的正则表达式代码获取带有相关量词的输出正则表达式量词中的混淆?JAVA,java,regex,Java,Regex,为什么我要为下面的正则表达式代码获取带有相关量词的输出ab Pattern p = Pattern.compile("abc*?"); Matcher m = p.matcher("abcfoo"); while(m.find()) System.out.println(m.group()); // ab 类似地,为什么要为下面的代码获取空索引 Pattern p = Pattern.compile(".*?"); Matcher m = p.m
ab
Pattern p = Pattern.compile("abc*?");
Matcher m = p.matcher("abcfoo");
while(m.find())
System.out.println(m.group()); // ab
类似地,为什么要为下面的代码获取空索引
Pattern p = Pattern.compile(".*?");
Matcher m = p.matcher("abcfoo");
while(m.find())
System.out.println(m.group());
*?
匹配零个或多个匹配,但尽可能少(顺便说一句,这通常称为“非贪婪”,而不是“不情愿”)。所以如果零匹配是可能的,那就是最佳匹配
你到底想要实现什么?也许你不需要非贪婪匹配。除了康拉德·鲁道夫的答案:
abc*?
在任何情况下匹配“ab”
,只有在必须匹配时才匹配“c”
。由于*?
之后没有任何内容,因此正则表达式引擎立即停止。如果你有:
abc*?f
然后它将匹配“abcf”
,因为“c”
必须匹配才能允许“f”
也匹配。另一种说法是:
.*?
不匹配任何内容,因为此模式是100%可选的
.*?f
将再次匹配“abcf”。将不情愿的量词作为正则表达式中的最后一项是没有意义的。一个不情愿的量词只能尽可能多地匹配,以实现整体匹配。这意味着在量词后面必须有一些东西来迫使它保持匹配
如果说有些东西可以被如此毫无意义地使用似乎有些奇怪的话,那可能是因为不情愿的量词是一个附加组件——这在“真正的”正则表达式中是不可能的。其他一些无意义用法的例子是带有量词的“量词”
{1}
,和\b+
或任何其他零宽度断言(^
,$
,lookarounds等)。有些口味将后者视为语法错误;Java允许它,但当然只应用一次断言。不情愿的量词使*
匹配尽可能少的字符,如果回溯需要,只匹配更多字符
下面是一个使用正则表达式查找非空前缀的示例,该前缀也是字符串的后缀(无重叠)
第一个模式中的捕获组\1
是贪婪的:它首先匹配所有内容,并在回溯时获取尽可能少的内容。因此,模式将找到最长的前缀/后缀匹配:
System.out.println(
"abracadabra".replaceAll("^(.+).*\\1$", "($1)")
); // prints "(abra)"
System.out.println(
"abracadabra".replaceAll("^(.+?).*\\1$", "($1)")
); // prints "(a)"
现在第二种模式中的\1
是不情愿的;它首先不匹配任何内容,并在回溯时获取更多内容。因此,模式将找到最短的前缀/后缀匹配:
System.out.println(
"abracadabra".replaceAll("^(.+).*\\1$", "($1)")
); // prints "(abra)"
System.out.println(
"abracadabra".replaceAll("^(.+?).*\\1$", "($1)")
); // prints "(a)"
在您的例子中,*?
可以匹配一个空字符串,并且不需要回溯和匹配更多的字符串,因为它足以匹配整个模式
另见
下面是有限重复中不情愿量词的另一个示例: 在这里,
x{3,5}
是贪婪的,并且将尽可能多地使用它
System.out.println(
"xxxxxxx".replaceAll("x{3,5}", "Y")
); // prints "Yxx"
System.out.println(
"xxxxxxx".replaceAll("x{3,5}?", "Y")
); // prints "YYx"
在这里,x{3,5}?
是不情愿的,并且会尽可能少地使用
System.out.println(
"xxxxxxx".replaceAll("x{3,5}", "Y")
); // prints "Yxx"
System.out.println(
"xxxxxxx".replaceAll("x{3,5}?", "Y")
); // prints "YYx"
Java称之为“不情愿”。我认为“不情愿”是对他们最好的称呼,尽管“不贪婪”也很好。但“懒惰”(另一个最常见的形容词)在我看来是误导性的;他们实际上比贪婪或占有量词更努力。@Alan Moore:我同意,“懒惰”在CS中通常是其他意思(参见懒惰评估)。