如何在Golang中去除字符串周围的引号

25

我在 Golang 中有一个被引号包围的字符串。我的目标是删除两侧的所有引号,但忽略字符串内部的引号。我该如何做?我的直觉告诉我可以像 C# 中使用 RemoveAt 函数一样,但我在 Go 中找不到类似的函数。

例如:

"hello""world"

应该转换为:

hello""world

为进一步澄清,这个:

"""hello"""

将变成这样:

""hello""

因为只有外部的应该被移除。

5个回答

41

使用 切片表达式

s = s[1 : len(s)-1]

如果有可能引号不存在,则使用以下内容:

if len(s) > 0 && s[0] == '"' {
    s = s[1:]
}
if len(s) > 0 && s[len(s)-1] == '"' {
    s = s[:len(s)-1]
}

playground示例


为什么要两次使用 len(s)?为什么不像这样嵌套使用:if len(s) { if s[0] == '"' { s = s[1:] } if s[len(s)-1] == '"' { s = s[:len(s)-1] } } - apokaliptis
@apokaliptis 答案检查 len(s) 两次以处理输入 ". - Charlie Tumahai
我尝试了两种在HTML模板中呈现字符串的方法,在这两种情况下,它们都去掉了结果中的引号,即:<p>"这是带引号但缺少第一个和最后一个字符的字符串"</p>。 - Alan Carlyle
@AlanCarlyle:看起来你使用了第一种方法,从字符串中删除第一个和最后一个字节,无论这些字节是什么(b)模板正在添加引号。如果您还没有弄清楚程序的问题,应该提出一个新问题。 - Charlie Tumahai
@CeriseLimón 我相当确定go html/template会自动添加引号,因为我知道我没有将它们放在字符串中。我已经寻找了解决该问题的答案,大多数只是处理如何在html中转义引号以便显示。 - Alan Carlyle

13

strings.Trim()函数可以用来去除字符串开头和结尾的空格。但如果双引号在字符串内部,该函数将无法生效。

// strings.Trim() will remove all the occurrences from the left and right

s := `"""hello"""`
fmt.Println("Before Trim: " + s)                    // Before Trim: """hello"""
fmt.Println("After Trim: " + strings.Trim(s, "\"")) // After Trim: hello

// strings.Trim() will not remove any occurrences from inside the actual string

s2 := `""Hello" " " "World""`
fmt.Println("\nBefore Trim: " + s2)                  // Before Trim: ""Hello" " " "World""
fmt.Println("After Trim: " + strings.Trim(s2, "\"")) // After Trim: Hello" " " "World

游乐场链接 - https://go.dev/play/p/yLdrWH-1jCE


1
如果我知道输入字符串的格式,那么“Trim”非常方便。 - Kenji Noguchi
2
这会修剪开头和结尾的多个引号,对吗?作者只想修剪一组引号。 - jdizzle

3

使用切片表达式。您应编写健壮的代码,以提供对不完善输入的正确输出。例如,

package main

import "fmt"

func trimQuotes(s string) string {
    if len(s) >= 2 {
        if s[0] == '"' && s[len(s)-1] == '"' {
            return s[1 : len(s)-1]
        }
    }
    return s
}

func main() {
    tests := []string{
        `"hello""world"`,
        `"""hello"""`,
        `"`,
        `""`,
        `"""`,
        `goodbye"`,
        `"goodbye"`,
        `goodbye"`,
        `good"bye`,
    }

    for _, test := range tests {
        fmt.Printf("`%s` -> `%s`\n", test, trimQuotes(test))
    }
}

输出:

`"hello""world"` -> `hello""world`
`"""hello"""` -> `""hello""`
`"` -> `"`
`""` -> ``
`"""` -> `"`
`goodbye"` -> `goodbye"`
`"goodbye"` -> `goodbye`
`goodbye"` -> `goodbye"`
`good"bye` -> `good"bye`

2
您可以利用切片来删除切片的第一个和最后一个元素。
package main

import "fmt"

func main() {
    str := `"hello""world"`

    if str[0] == '"' {
        str = str[1:]
    }
    if i := len(str)-1; str[i] == '"' {
        str = str[:i]
    }

    fmt.Println( str )
}

由于切片共享底层内存,因此这不会复制字符串。它只是将str切片更改为从一个字符开始,到少一个字符结束。

这就是各种字节修剪函数的工作原理。


@CeriseLimón 谢谢,我还在学习字符串和[]byte之间的关系。我曾经有一个页面解释了何时会发生复制,何时不会,但是我把它弄丢了。你有相关资源吗? - Schwern

0

使用正则表达式的一行代码...

quoted = regexp.MustCompile(`^"(.*)"$`).ReplaceAllString(quoted,`$1`)

但它并不一定以你想要的方式处理转义引号。

Go Playground

翻译自这里


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