替换除最后一次出现以外的所有字符

我正在对这样的字符串执行字符替换:

result = strings.ReplaceAll(result, ".", "_")

这按预期工作,但我想保留最后一次出现的.而不是替换它,只是让它独自一人。

有没有一种奇特的方法可以做到这一点?


梦里花落0921
浏览 111回答 4
4回答

SMILET

分成[]string, 然后Join除最后 ;)func ReplaceAllButLast(data, old, new string) string {&nbsp; &nbsp; split := strings.Split(data, old)&nbsp; &nbsp; if len(split) < 3 {&nbsp; &nbsp; &nbsp; &nbsp; return data&nbsp; &nbsp; }&nbsp; &nbsp; last := len(split) - 1&nbsp; &nbsp; return strings.Join(split[:last], new) + old + split[last]}https://go.dev/play/p/j8JJP-p_Abkfunc main() {&nbsp; &nbsp; println(ReplaceAllButLast("a", ".", "_"))&nbsp; &nbsp; println(ReplaceAllButLast("a.b", ".", "_"))&nbsp; &nbsp; println(ReplaceAllButLast("a.b.c", ".", "_"))&nbsp; &nbsp; println(ReplaceAllButLast("a.b.c.d", ".", "_"))}生产的aa.ba_b.ca_b_c.d更新那是个玩笑,只是为了花哨最好的方法是计算匹配次数并替换Count()-1,第二个ReplaceAll直到最后一个匹配位置并使用Join最慢func ReplaceAllButLast_Count(data, old, new string) string {&nbsp; &nbsp; cnt := strings.Count(data, old)&nbsp; &nbsp; if cnt < 2 {&nbsp; &nbsp; &nbsp; &nbsp; return data&nbsp; &nbsp; }&nbsp; &nbsp; return strings.Replace(data, old, new, cnt-1)}func ReplaceAllButLast_Replace(data, old, new string) string {&nbsp; &nbsp; idx := strings.LastIndex(data, old)&nbsp; &nbsp; if idx <= 0 {&nbsp; &nbsp; &nbsp; &nbsp; return data&nbsp; &nbsp; }&nbsp; &nbsp; return strings.ReplaceAll(data[:idx], old, new) + data[idx:]}func ReplaceAllButLast_Join(data, old, new string) string {&nbsp; &nbsp; split := strings.Split(data, old)&nbsp; &nbsp; if len(split) < 3 {&nbsp; &nbsp; &nbsp; &nbsp; return data&nbsp; &nbsp; }&nbsp; &nbsp; last := len(split) - 1&nbsp; &nbsp; return strings.Join(split[:last], new) + old + split[last]}基准使用a.b.c.d -> a_b_c.dgoos: windowsgoarch: amd64pkg: example.orgcpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHzBenchmark_Count-8&nbsp; &nbsp; &nbsp; &nbsp;16375098&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 70.05 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 8 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 allocs/opBenchmark_Replace-8&nbsp; &nbsp; &nbsp;11213830&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;108.5 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 16 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 allocs/opBenchmark_Slice-8&nbsp; &nbsp; &nbsp; &nbsp; 5460445&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;217.6 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 80 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 allocs/op

慕勒3428872

处理这个问题最明显的方法是结合Replaceand Count:func ReplaceAllExceptLast(d string, o string, n string) string {&nbsp; &nbsp; strings.Replace(d, o, n, strings.Count(d, o) - 1)}但是,我认为这不是最佳解决方案。对我来说,最好的选择是这样做:func ReplaceAllExceptLast(d string, o string, n string) string {&nbsp; &nbsp; ln := strings.LastIndex(d, o)&nbsp; &nbsp; if ln == -1 {&nbsp; &nbsp; &nbsp; &nbsp; return d&nbsp; &nbsp; }&nbsp; &nbsp; return strings.ReplaceAll(d[:ln], o, n) + d[ln:]}这是通过获取要替换的值的最后一次出现的索引,然后对字符串进行全部替换直到该点。例如:println(ReplaceAllExceptLast("a", ".", "_"))println(ReplaceAllExceptLast("a.b", ".", "_"))println(ReplaceAllExceptLast("a.b.c", ".", "_"))println(ReplaceAllExceptLast("a.b.c.d", ".", "_"))将产生:aa.ba_b.ca_b_c.d

牛魔王的故事

我想到的第一个解决方案是Positive Lookahead正则表达式[.](?=.*[.])但是, Golang&nbsp;re2(?=re)不支持我们可以用Non-capturing group这种方式来实现首先使用&nbsp;(?:[.])( Match a single character present in the list below [.]) 来查找所有点索引。然后用'_'代替最后一个点。样本func replaceStringByIndex(str string, replacement string, index int) string {&nbsp; &nbsp; return str[:index] + replacement + str[index+1:]}func replaceDotIgnoreLast(str string, replacement string) string {&nbsp; &nbsp; pattern, err := regexp.Compile("(?:[.])")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return ""&nbsp; &nbsp; }&nbsp; &nbsp; submatches := pattern.FindAllStringSubmatchIndex(str, -1)&nbsp; &nbsp; for _, submatch := range submatches[:len(submatches)-1] {&nbsp; &nbsp; &nbsp; &nbsp; str = replaceStringByIndex(str, replacement, submatch[0])&nbsp; &nbsp; }&nbsp; &nbsp; return str}func main() {&nbsp; &nbsp; str := "1.2"&nbsp; &nbsp; fmt.Println(replaceDotIgnoreLast(str, "_"))&nbsp; &nbsp; str = "1.2.3"&nbsp; &nbsp; fmt.Println(replaceDotIgnoreLast(str, "_"))&nbsp; &nbsp; str = "1.2.3.4"&nbsp; &nbsp; fmt.Println(replaceDotIgnoreLast(str, "_"))}结果1.21_2.31_2_3.4

小怪兽爱吃肉

使用strings.Count来计算要替换的字符串出现的次数将 count-1 传递给strings.Replace以省略最后一次出现func&nbsp;ReplaceAllButLast(input&nbsp;string,&nbsp;find&nbsp;string,&nbsp;replace&nbsp;string)&nbsp;string&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;occurrencesCount&nbsp;:=&nbsp;strings.Count(input,&nbsp;find) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;strings.Replace(input,&nbsp;find,&nbsp;replace,&nbsp;occurrencesCount-1) }
打开App,查看更多内容
随时随地看视频慕课网APP