一尘不染

去ReplaceAllString

go

我从golang.org网站上阅读了示例代码。本质上,代码如下所示:

re := regexp.MustCompile("a(x*)b")
fmt.Println(re.ReplaceAllString("-ab-axxb-", "T"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "${1}W"))

输出如下:

-T-T-
--xx-
---
-W-xxW-

我了解第一个输出,但不了解其余三个。有人可以向我解释结果2,3和4。谢谢。


阅读 220

收藏
2020-07-02

共1个答案

一尘不染

最吸引人的是这fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W"))条线。该文件说

在repl内部,$符号解释为Expand

展开说:

在模板中,变量由$name或形式的子字符串表示${name},其中name是字母,数字和下划线的非空序列。
对超出范围或不匹配的索引的引用或在正则表达式中不存在的名称将替换为空切片。

$name形式中,名称应尽可能长:$1x等于${1x},不等于${1}x,并且$10等于${10},不等于${1}0

因此,在第三更换,$1W被视为${1W}由于此群体不被初始化,一个空字符串用于替换。

当我说“该组未初始化”时,我的意思是说该组未在正则表达式模式中定义,因此,在 匹配 操作期间未填充该组。 替换
意味着获取所有匹配项,然后将它们替换为替换模式。在 匹配 阶段将填充 反向引用$xx构造)。该模式中缺少该组,因此在 匹配
期间未填充该组,并且在发生 替换 阶段时仅使用一个空字符串。 $1W __

第二个和第四个替换项很容易理解,上面的答案中对此进行了描述。只是$1反向引用字符 捕获
与所述第一捕获组(封闭具有一对未转义括号的子模式),同样是用实施例4。

您可以认为{}这是 消除 替换模式 歧义 的一种方法。

现在,如果需要使结果一致,请使用 命名捕获 (?P<1W>....)

re := regexp.MustCompile("a(?P<1W>x*)b")  // <= See here, pattern updated
fmt.Println(re.ReplaceAllString("-ab-axxb-", "T"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W"))
fmt.Println(re.ReplaceAllString("-ab-axxb-", "${1}W"))

结果:

-T-T-
--xx-
--xx-
-W-xxW-

现在,第二行和第三行产生一致的输出,因为命名组1W也是 第一 组,并且$1编号的反向引用指向使用命名捕获捕获的相同文本$1W

2020-07-02