4

有一个关于正则表达式的问题,试图回答我发现了另一个奇怪的事情。

String x = "X";
System.out.println(x.replaceAll("X*", "Y"));

这将打印 YY。为什么??

String x = "X";
System.out.println(x.replaceAll("X*?", "Y"));

这会打印 YXY

为什么不情愿的正则表达式与“X”字符不匹配?有"noting"X"nothing"但是为什么首先不匹配三个符号并匹配两个然后一个而不是三个?第二个正则表达式只匹配"nothing"s 而不是X?

4

3 回答 3

8

让我们依次考虑它们:

"X".replaceAll("X*", "Y")

有两场比赛:

  1. 在字符位置 0,X匹配,并替换为Y.
  2. 在字符位置 1,空字符串被匹配,Y并被添加到输出中。

最终结果:YY

"X".replaceAll("X*?", "Y")

还有两场比赛:

  1. 在字符位置 0,空字符串被匹配,Y并被添加到输出中。该位置的字符X没有被匹配消耗,因此被逐字复制到输出中。
  2. 在字符位置 1,空字符串被匹配,Y并被添加到输出中。

最终结果:YXY

于 2012-02-10T13:35:38.773 回答
1

* 是一个棘手的“量词”,因为它表示“0 或更多”。因此,它也匹配“0 次 X”(即空字符串)。

我会用

"X".replaceAll("X+", "Y")

具有预期的行为。

于 2012-02-10T13:40:50.570 回答
0

在您的第一个示例中,您使用的是“贪婪”量词。这意味着在尝试第一个匹配之前强制读取输入字符串,因此尝试的第一个匹配是整个输入。如果输入匹配,匹配器会越过输入字符串并在字符串末尾执行零长度匹配,因此您会看到两个匹配项。在第一次匹配尝试成功之前,贪婪匹配器永远不会回退到字符 X 之前的零长度匹配。

在第二个示例中,您使用的是与“贪婪”相反的“不情愿”量词。它从一开始就尝试匹配一个字符(如果必须)。所以匹配“X”字符之前的零长度匹配,匹配器向前移动一个(这就是为什么你仍然在输出中看到“X”字符),下一个匹配现在是“X”之后的零长度匹配”。
这里有一个很好的教程:http: //docs.oracle.com/javase/tutorial/essential/regex/quant.html

于 2012-02-10T14:18:06.180 回答