strings.ReplacePairs
返回给定字符串,并用一组旧新字符串对在一次扫描中完成多处替换。
(0.158.0 新增)
用 strings.ReplacePairs 函数可以在一次操作中对字符串完成多处替换,这比依次调用 strings.Replace 函数更快。
依次替换需要多次函数调用与变量重新赋值:
{{ $s := "aabbcc" }}
{{ $s = strings.Replace $s "a" "x" }}
{{ $s = strings.Replace $s "b" "y" }}
{{ $s = strings.Replace $s "c" "z" }}
{{ $s }} → xxyyzz使用 strings.ReplacePairs 可以用更少的函数调用、在更短的时间内得到相同结果:
{{ "aabbcc" | strings.ReplacePairs "a" "x" "b" "y" "c" "z" }} → xxyyzz各对字符串也可以放在一个切片中传入:
{{ $pairs := slice
"a" "x"
"b" "y"
"c" "z"
}}
{{ "aabbcc" | strings.ReplacePairs $pairs }} → xxyyzz示例
注意:由于该函数只扫描字符串一次,替换不会递归进行。
{{ $pairs := slice
"a" "b"
"b" "c"
}}
{{ "a" | strings.ReplacePairs $pairs }} → b当多个旧字符串都能在同一位置匹配时,应用最先匹配的那一个。
{{ $pairs := slice
"app" "pear"
"apple" "orange"
}}
{{ "apple" | strings.ReplacePairs $pairs }} → pearle把一对中的第二个值写成空字符串,即可删除指定的字符串。
{{ $pairs := slice "b" "" }}
{{ "abc" | strings.ReplacePairs $pairs }} → ac边界情况
下表说明该函数如何处理各种输入情况。
| 场景 | 结果 |
|---|---|
| 参数少于两个 | 报错 |
| 切片元素个数为奇数 | 报错 |
| 空切片 | 返回输入字符串 |
| 输入字符串为空 | 返回空字符串 |
| 旧字符串为空 | 返回输入字符串与新字符串交错(interleaved)后的结果 |
性能
strings.Replace 与 strings.ReplacePairs 虽然可以得到相同的结果,但处理数据的方式不同。选对函数可以明显缩短 Hugo 构建项目所需的时间。
单次扫描与多次扫描
使用 strings.Replace 时,Hugo 必须从头到尾扫描文本才能找到匹配。如果把三次替换串联在一起,Hugo 就要对整个字符串做三次独立的扫描。
strings.ReplacePairs 函数更高效,因为它只做一次扫描:Hugo 只遍历文本一遍,同时应用所有替换。
缓存
strings.Replace 执行的是直接替换,而 strings.ReplacePairs 需要先完成一步初始化,准备好单次扫描的替换逻辑。为了保持高效,Hugo 用缓存来管理这套逻辑:
- 首次调用时,Hugo 初始化并存储该组旧新字符串对应的逻辑。
- 后续调用时,Hugo 取出已存储的逻辑,跳过初始化步骤,从而缩短调用耗时。
如何选择函数
文本越长、旧新字符串对越多,strings.ReplacePairs 的效率优势越明显。决定用哪个函数时,可以参考以下情形:
- 对标题这类短字符串做单次替换时,
strings.Replace更高效。 - 需要多处替换,或处理长文这类长字符串时,
strings.ReplacePairs快得多。
对于约 8000 字符的文档(大致相当于一篇长文的长度),即使在首次调用时,strings.ReplacePairs 也比连续调用五次 strings.Replace 更快。一旦命中缓存,只要有两对或更多旧新字符串,几乎在任何情况下它都是更快的选择。