为什么我使用Relucutant量词得到以下正则表达式代码的输出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());
答案 0 :(得分:7)
除了Konrad Rudolph的回答:
abc*?
在任何情况下都匹配"ab"
,只有必须才匹配"c"
。由于*?
之后没有任何内容,因此正则表达式引擎会立即停止。如果你有:
abc*?f
然后它会与"abcf"
匹配,因为"c"
必须匹配,以便"f"
也匹配。另一个表达:
.*?
不匹配任何内容,因为此模式是100%可选的。
.*?f
会再次匹配"abcf"
。
答案 1 :(得分:5)
*?
匹配零个或多个匹配,但尽可能少(顺便说一下,通常称为“非贪婪”,而不是“不情愿”)。因此,如果零匹配是可能的,那就是最佳匹配。
您想要达到什么目标?也许非贪婪的匹配不是你需要的。
答案 2 :(得分:2)
将一个不情愿的量词作为正则表达式中的最后一件事是没有意义的。为了实现整体匹配,不情愿的量词仅与其必须匹配。这意味着在量词之后必须有一些来强制它保持匹配。
如果看起来很奇怪有些东西可以被用得如此毫无意义,那可能是因为不情愿的量词是一个附加物 - 这是“真正的”正则表达式无法实现的。其他一些无意义使用的例子是“量词”{1}
,\b+
或任何其他零宽度断言(^
,$
,外观等等)量词。有些风格将后者视为语法错误; Java允许它,但当然只应用断言一次。
答案 3 :(得分:2)
?
不情愿的量词使.*
匹配尽可能少的字符,只有匹配更多字符才能回溯。
以下是使用正则表达式查找非空前缀的说明性示例,该前缀也是字符串的后缀(不重叠)。
第一种模式中的捕获组\1
是贪婪的:它首先匹配所有内容,并且尽可能少地回溯。因此,模式将找到最长的前缀/后缀匹配:
System.out.println(
"abracadabra".replaceAll("^(.+).*\\1$", "($1)")
); // prints "(abra)"
现在\1
在第二种模式中是不情愿的;它首先匹配任何东西,并且在回溯时需要更多。因此,模式将找到最短的前缀/后缀匹配:
System.out.println(
"abracadabra".replaceAll("^(.+?).*\\1$", "($1)")
); // prints "(a)"
在您的情况下,.*?
可以匹配空字符串,并且永远不需要回溯和匹配更多,因为它足以使整个模式匹配。
这是有限重复的不情愿量词的另一个说明性例子:
在这里,x{3,5}
是贪婪的,并且会尽可能多地使用。
System.out.println(
"xxxxxxx".replaceAll("x{3,5}", "Y")
); // prints "Yxx"
在这里,x{3,5}?
不情愿,并且会尽可能少。
System.out.println(
"xxxxxxx".replaceAll("x{3,5}?", "Y")
); // prints "YYx"
答案 4 :(得分:0)
*?-> also call it as Lasy star
^abc*?f
*?----> repeats 0 or more times
^---> regular expression for start of the string
Example: abcf00abcf00 --->Matches:"abcf"00abcf00
In this case c must select to reach f
abc*?
*?----> repeats 0 or more times
Matches ab
Example: abcabcabcabc -----> Matches:"ab"c"ab"c"ab"c"ab"c
abc.* matches any character except line break
Example: abcabababbababab --->Matches:"abcabababbababab"
ab.*?
example: ababababbababab ---> "ab""ab""ab""ab""ab""ab""ab""ab"
abc? matsches ab or abc