昨天有同事在看k8s源码,突然问了一个看似很简单的问题,https://golang.org/pkg/regexp/#Regexp.ReplaceAllString 官方文档中ReplaceAllString
的解释,到底是什么意思?到底怎么用?
官方英文原文:
func (re *Regexp) ReplaceAllString(src, repl string) string
1 |
|
中文文档:
1 | ReplaceAllLiteral返回src的一个拷贝,将src中所有re的匹配结果都替换为repl。在替换时,repl中的'$'符号会按照Expand方法的规则进行解释和替换,例如$1会被替换为第一个分组匹配结果。 |
看上去一脸懵逼,还是不理解这个函数到底怎么用。
又去看官方的示例:
1 | Example: |
第一个替换勉强能看明白,是用T
去替换-ab-axxb-
中符合正则表达式匹配的部分;第二个中的$
是什么意思?$1
看起来像是匹配正则表达式分组中第一部分,那$1W
呢?${1}W
呢?带着这些问题,开始深入研究这个函数到底怎么用。
首先,$
符号在Expand
函数中有解释过:
1 | func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte |
说了这么多,其实最终要的部分可以概括为三点:
$
后面只有数字,则代表正则表达式的分组索引,关于正则表达式的分组解释:
捕获组可以通过从左到右计算其开括号来编号 。例如,在表达式 (A)(B(C)) 中,存在四个这样的组:
0 | (A)(B(C)) |
---|---|
1 | (A) |
2 | (B(C)) |
3 | (C) |
组零始终代表整个表达式
之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用(反向引用) 在表达式中使用,也可以在匹配操作完成后从匹配器检索。
匹配正则表达式的$1
部分,保留该部分,去掉其余部分;
$
后面是字符串,即$name
,代表匹配对应(?P…)语法产生的命名捕获分组的名字 ${数字}字符串
,即${1}xxx
,意思是匹配正则表达式的分组1,src
中匹配分组1的保留,并删除src
剩余部分,追加xxx
,后面会有代码示例解释这部分,也是最难理解的部分- 最简单的情况,参数
repl
是字符串,将src中所有re的匹配结果都替换为repl
下面用代码来解释以上几种情况:
1 | package main |
上面代码输出依次是:
1 | go run main.go |
总结
Goregexp
包中的ReplaceAllString
设计有些许反人类,理解和使用上感觉不方便,如果你有更好的理解或者示例代码,Call me!