一尘不染

为什么(。*)*进行两次匹配并在组$ 1中什么也不选择?

java

这源于对正则表达式语法形式化的讨论。我已经通过几个正则表达式解析器看到了此行为,因此我将其标记为与语言无关。

采取以下表达式(针对您喜欢的语言进行调整):

replace("input", "(.*)*", "$1")

它将返回一个空字符串。为什么?

更奇怪的是,表达式replace("input", "(.*)*", "A$1B")将返回string ABAB。为什么双空比赛?

免责声明:
我知道回溯和贪婪的匹配,但是杰弗里·弗里德尔制定的规则似乎规定,.*匹配所有内容,并且不再进行进一步的回溯或匹配。那为什么是$1空的?

注意:
与比较(.+)*,返回输入字符串。但是,http://regexhero.com显示仍存在两个匹配项,出于与上述相同的原因,这似乎很奇怪。


阅读 149

收藏
2020-12-03

共1个答案

一尘不染

让我们看看发生了什么:

  1. (.*)火柴"input"
  2. "input"被分组1
  3. 正则表达式引擎现在位于字符串的末尾。但是由于(.*)重复执行,因此将进行另一次匹配尝试:
  4. (.*)与后面的空字符串匹配"input"
  5. 空字符串被捕获到组1,覆盖"input"
  6. $1 现在包含空字符串。

评论中的一个好问题:

那为什么还replace("input", "(input)*", "A$1B")回来"AinputBAB"呢?

  1. (input)*火柴"input"。替换为"AinputB"
  2. (input)*匹配空字符串。它被替换为"AB"$1为空,因为它没有参加比赛)。
  3. 结果: "AinputBAB"
2020-12-03