【问题标题】:Replace every nth instance of character in string替换字符串中每个第 n 个字符实例
【发布时间】:2017-12-01 11:55:27
【问题描述】:

我对 Go 有点陌生,但我试图用逗号替换字符串的每个第 n 个实例。例如,我的一部分数据如下所示:

"2017-06-01T09:15:00+0530",1634.05,1635.95,1632.25,1632.25,769,"2017-06-01T09:16:00+0530",1632.25,1634.9,1631.65,1633.5,506,"2017-06-01T09:17:00+0530",1633.5,1639.95,1633.5,1638.4,991,

我想用'\n' 替换every 6th comma,所以它看起来像

"2017-06-01T09:15:00+0530",1634.05,1635.95,1632.25,1632.25,769"
"2017-06-01T09:16:00+0530",1632.25,1634.9,1631.65,1633.5,506"
"2017-06-01T09:17:00+0530",1633.5,1639.95,1633.5,1638.4,991"

我查看了regexp 包,这似乎是一个发现者。 strings 包确实有一个替换,但我不知道如何使用它来替换特定的索引。我也不知道如何在不逐个字符遍历整个字符串的情况下找到特定索引。我想知道是否有比我编写辅助函数更优雅的 regEx 解决方案。 字符串是不可变的,所以我无法就地编辑它们。

编辑:将字符串转换为 [] 字节。这使我可以就地编辑字符串。然后剩下的就是一个相当简单的 for 循环,其中dat 是数据。

【问题讨论】:

  • 请发布您的尝试,并说明问题所在。

标签: regex string go replace


【解决方案1】:

如果这是您的输入,您应该将," 字符串替换为\n"。您可以为此使用strings.Replace()。这将留下最后一个尾随逗号,您可以通过切片将其删除。

解决方案:

in := `"2017-06-01T09:15:00+0530",1634.05,1635.95,1632.25,1632.25,769,"2017-06-01T09:16:00+0530",1632.25,1634.9,1631.65,1633.5,506,"2017-06-01T09:17:00+0530",1633.5,1639.95,1633.5,1638.4,991,`
out := strings.Replace(in, ",\"", "\n\"", -1)
out = out[:len(out)-1]
fmt.Println(out)

输出是(在Go Playground上试试):

"2017-06-01T09:15:00+0530",1634.05,1635.95,1632.25,1632.25,769
"2017-06-01T09:16:00+0530",1632.25,1634.9,1631.65,1633.5,506
"2017-06-01T09:17:00+0530",1633.5,1639.95,1633.5,1638.4,991

【讨论】:

  • 谢谢!有几件事:(1) Replace 函数在这种情况下究竟是如何工作的。我在我的字符串中没有看到\" 的模式,所以每次替换它到底找到了什么。 (2)我的文件中每一行的末尾仍然有逗号;有没有办法从每行的末尾删除?
  • @S2C 这是一个interpreted string literal\" 表示单引号(因为引号本身意味着字符串文字的结尾)。它找到," 文本并将它们替换为换行符加引号。正是您需要的。
  • 谢谢!我看到你正在利用这样一个事实,即我想用新行替换的逗号后面总是有一个引号。虽然这在这种情况下有效,但在其他情况下我必须做类似的事情,其中​​唯一不变的模式是要替换字符的第 n 个实例。
  • string.Replace() 接受一个要替换的字符串,接下来要替换的部分,接下来要替换的内容,最后要替换多少个。 -1 表示没有限制。
  • @S2C 是的,我已经利用了您输入的结构,因此解决方案非常简单。这不是一般的“第 n 个替代者”。
【解决方案2】:

如果你想要灵活。

package main

import (
    "fmt"
    "strings"
)

func main() {
    input := `"2017-06-01T09:15:00+0530",1634.05,1635.95,1632.25,1632.25,769,"2017-06-01T09:16:00+0530",1632.25,1634.9,1631.65,1633.5,506,"2017-06-01T09:17:00+0530",1633.5,1639.95,1633.5,1638.4,991,`
    var result []string

    for len(input) > 0 {
        token := strings.SplitN(input, ",", 7)
        s := strings.Join(token[0:6], ",")
        result = append(result, s)
        input = input[len(s):]
        input = strings.Trim(input, ",")
    }
    fmt.Println(result)
}

https://play.golang.org/p/mm63Hx24ne

【讨论】:

    【解决方案3】:

    所以我发现我做错了什么。我最初将数据作为string,但如果我将其转换为byte[],那么我可以就地更新它。

    这让我可以在下面使用一个简单的for 循环来解决问题,而无需依赖除第 n 个字符实例之外的任何其他指标

    for i := 0; i < len(dat); i++ {
        if dat[i] == ',' {
            count += 1
        }
        if count%6 == 0 && dat[i] == ',' {
            dat[i] = '\n'
            count = 0
        }
    

    【讨论】:

    • 在处理字符串时,在这些场景中将其视为 []rune
    • 为什么符文更受欢迎?
    • 你可能认为的字符常量在 Go 中称为rune 常量。 rune 可以包含一个完整的 unicode 字符(32 位),而 byte 只能包含 8 个字节。对于只有 ASCII 字符的字符串,将字符串视为 []byte 很好,但当它有其他 unicode 字符时它会失败
    猜你喜欢
    • 1970-01-01
    • 2013-08-18
    • 2017-11-15
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2015-08-21
    • 2020-08-05
    • 1970-01-01
    相关资源
    最近更新 更多