【问题标题】:Go ReplaceAllString去替换所有字符串
【发布时间】:2016-04-12 21:35:07
【问题描述】:

我从golang.org website 阅读了示例代码。基本上代码如下所示:

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。谢谢。

【问题讨论】:

  • 您是否阅读了示例代码上方的文字?
  • 是的,我读到了。但我仍然不明白扩展是如何工作的。

标签: regex go


【解决方案1】:

最有趣的是fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W")) 行。 docs say

在repl中,$符号被解释为Expand

Expand 说:

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

$name形式中,取名字尽可能长:$1x等价于${1x},而不是${1}x,并且,$10等价于${10},不是${1}0

因此,在第 3 次替换中,$1W 被视为 ${1W},并且由于该组未初始化,因此使用空字符串进行替换。

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

第 2 次和第 4 次替换很容易理解,并且已在上述答案中进行了描述。只是 $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 编号的反向引用指向使用命名捕获@987654346 捕获的相同文本@。

【讨论】:

  • this group is not initialized 是什么意思?如何初始化一个组?很抱歉我的问题可能很幼稚。
  • 该组未在正则表达式模式中指定,因此在匹配操作期间未填充。替换意味着获取所有匹配项,然后将它们替换为替换模式。 反向引用$xx 构造)在匹配阶段填充。模式中缺少$1W 组,因此在匹配期间未填充它,并且在发生替换阶段时仅使用空字符串。
  • 如果我愿意,应该怎么做才能使 1W 美元存在?我正在尝试了解有关指定组的知识。
  • 使用re := regexp.MustCompile("a(?P&lt;1W&gt;x*)b"),那么第2行和第3行的结果是一样的。我用它更新了答案。
【解决方案2】:

$1${1} 的简写

${1} 是第一个 (1) 组的值,例如第一对 () 的内容。该组是(x*),即任意数量的x

ReplaceAllString 替换每个匹配项。有两场比赛。第一个是ab,第二个是axxb

否 2. 将任何匹配替换为组的内容:这是第一个匹配中的“”,第二个匹配中的“xx”。

No 4. 在分组内容后加一个“W”。

没有 3。留作练习。提示:第十二个捕获组将是 12 美元。

【讨论】:

  • 所以我可以理解为每场比赛的替换都是动态的吗?
  • 谢谢。您的回答帮助我理解了第二个输出。
  • 我们在这里写数学书不是为了做练习。
【解决方案3】:

$number 或 $name 是正则表达式或子组名称中子组的索引

fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1"))

$1 是正则表达式中的子组 1 = x*

fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W"))

$1W 没有子组名称 1W => 全部替换为 null

fmt.Println(re.ReplaceAllString("-ab-axxb-", "${1}W"))

$1 和 ${1} 是一样的。用 W 替换所有子组 1

更多信息:https://golang.org/pkg/regexp/

【讨论】:

  • 谢谢。你能多解释一下第二个结果吗?
  • 好的,$name $后面的所有字符都是名字,所以没有替换键=>替换键=null,如果找不到组名,它将使用默认的正则表达式a(x*)b并替换带空键
  • 感谢您让我了解命名组。
猜你喜欢
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 2016-09-26
相关资源
最近更新 更多