替换字符串中除了最后四个字符之外的所有字符

4
使用Go语言,如何将字符串中除最后4个字符外的所有字符替换为“X”?
这在php/javascript中可以正常工作,但在Golang中不支持“?=”。
\w(?=\w{4,}$)

尝试了这个,但不起作用。我找不到类似于 golang 的东西。
(\w)(?:\w{4,}$)

JavaScript工作链接

Go无法工作的链接


2
如果您发布最小的自包含可运行代码,那么您可以帮助他人更好地帮助您。 - Scott Stensland
抱歉,我在我的问题中添加了链接。 - raghzz
@raghzz 你一定要使用正则表达式吗?其实这个问题可以很容易地不用它就解决。 - sberry
@sberry 不是很确定。只要我们能够以良好的性能实现这一点就可以了。 - raghzz
4个回答

9
一个简单而有效的解决方案,可以处理多个UTF-8字节字符,即将string转换为[]rune,用'X'覆盖符文(除了最后4个),然后再转换回string
func maskLeft(s string) string {
    rs := []rune(s)
    for i := 0; i < len(rs)-4; i++ {
        rs[i] = 'X'
    }
    return string(rs)
}

测试它:

fmt.Println(maskLeft("123"))
fmt.Println(maskLeft("123456"))
fmt.Println(maskLeft("1234世界"))
fmt.Println(maskLeft("世界3456"))

输出结果(请在Go Playground上尝试):

123
XX3456
XX34世界
XX3456

还可以看相关问题:如何在golang中替换字符串中的所有字符


1
这是一个很好的解决方案! - Josh Withee
顺便提一下,for循环同样可以使用for i := range rs[:len(rs)-4]来代替手动处理迭代器。 - Kaedys
2
@Kaedys 但是如果传递的字符串长度小于4个符文,那么这样做会引发恐慌,而我的解决方案则不会。 - icza
如果您不需要担心UTF8字符(比如,如果字符串全部是ASCII字符,例如信用卡号码),将其转换为byte[]可能会更快。但这种速度提升可能并不值得担心。 - Milo Christiansen
公平。不过,如果长度小于5,您也可以很容易地短路返回。我只是不喜欢看到在可范围构造上使用手动迭代器。 - Kaedys
@Kaedys 我同意你的观点。我选择不使用 range 是因为这样看起来更简洁,更容易理解。 - icza

1
假设inputString是您想要屏蔽所有字符(除了最后四个字符)的字符串。
首先获取字符串的最后四个字符:
last4 := string(inputString[len(inputString)-4:])

接着获取一个长度与inputString相同但减去4个字符的X字符串:

re := regexp.MustCompile("\w")
maskedPart := re.ReplaceAllString(inputString[0:len(inputString)-5], "X")

然后将maskedPartlast4组合起来,以获得您的结果:
maskedString := strings.Join([]string{maskedPart,last4},"")

也许我可以从给这个帖子点踩的人那里得到一些有用的反馈? - Josh Withee
我不是点下投票的人,但这个解决方案(很可能)比循环版本更慢,涉及更多分配。正则表达式的答案可能比这个更慢,但因为提问者想要一个正则表达式,所以这个得过。 - Milo Christiansen
@MiloChristiansen 我同意icza提供了一个更有效的解决方案。当有一个可行的解决方案,但可能存在更快的解决方案时,应该使用downvotes吗?在这个帮助页面上,它说:“每当您遇到一个极其懒惰、没有付出努力的帖子或者一个明显且可能危险错误的答案时,请使用downvotes。” - Josh Withee
@MiloChristiansen 无论如何,我感谢您抽出时间给予反馈! - Josh Withee
“耸肩” 有些人会这样使用。我不会,而且我倾向于认为将工作正常的解决方案投反对票是一个坏主意,但其他人似乎并不总是同意。 - Milo Christiansen

1
更简单的方法,不需要使用正则表达式和循环。
package main

import (
    "fmt"
    "strings"
)

func main() {
    string := "thisisarandomstring"

    head := string[:len(string)-4]
    tail := string[len(string)-4:]

    mask := strings.Repeat("x", len(head))
    fmt.Printf("%v%v", mask, tail)
}

// Output:
// xxxxxxxxxxxxxxxring

你可以更简化这个代码,因为你实际上不需要“head”,只需要使用ins len(string-4)获取head的长度。 - swannee

0
创建一个带有Regexp的对象。
re := regexp.MustCompile("\w{4}$")

假设inputString是你想要从中删除最后四个字符的字符串。使用以下代码返回一个不包含最后4个字符的inputString副本:
re.ReplaceAllString(inputString, "")

注意:如果您的输入字符串可能以少于四个字符开头,并且您仍然希望删除这些字符,因为它们在字符串的末尾,那么您应该使用以下方法:
re := regexp.MustCompile("\w{0,4}$")

我不想删除它们,只需用“X”掩盖字符,但保留最后4个并返回字符串。例如:如果字符串是“TEST111”,则返回“XXXT111”。 - raghzz
re := regexp.MustCompile("\w{4}$"). re.ReplaceAllString(inputString, "XXX") 会替换掉最后4个字符。我该如何替换除最后4个字符外的其他字符? - raghzz
有些事情使用正则表达式是正确答案,但这并不是其中之一。当然,你可以这么做,但它比“正确”的方式要慢得多。 - Milo Christiansen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接