RegEx中的混淆不情愿量词? Java的

时间:2010-05-14 11:21:01

标签: java regex

为什么我使用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());

5 个答案:

答案 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