V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
guonaihong
V2EX  ›  程序员

golang 字符串技巧分享(1)--分割

  •  
  •   guonaihong ·
    guonaihong · 2019-10-10 09:27:30 +08:00 · 2747 次点击
    这是一个创建于 1868 天前的主题,其中的信息可能已经有所发展或是发生改变。

    开发过程中少不了要于字符串打交道。假如要对一个文本串进行分段,分割符是.?;. 还要保留分割符号,就不能使用常用的 string.Split 函数,Split 会把分割符去除。下面介绍两种方式。

    基于状态方法

    用时 2:42

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        const input = "1,2,3,4,5;6.7?"
        var all []string
    
        prev := 0
        for i := 0; i < len(input); i++ {
            switch input[i] {
            case ',', '.', ';', '?':
                all = append(all, input[prev:i+1])
                prev = i + 1 
            }
        }   
    
        for _, v := range all {
            fmt.Printf("%s\n", v)
        }   
    }
    
    

    基于 scanner

    用时 1:28(复制官网例子,修改回调函数的内容,所以用时很短)

    package main
    
    import (
        "bufio"
        "fmt"
        "os"
        "strings"
    )
    
    func main() {
        // Comma-separated list; last entry is empty.
        const input = "1,2,3,4,5;6.7?"
        scanner := bufio.NewScanner(strings.NewReader(input))
        // Define a split function that separates on commas.
        onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
            for i := 0; i < len(data); i++ {
                switch data[i] {
                case ',', '.', ';', '?':
                    return i + 1, data[:i+1], nil 
                }   
            }
            if !atEOF {
                return 0, nil, nil 
            }   
            // There is one final token to be delivered, which may be the empty string.
            // Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this
            // but does not trigger an error to be returned from Scan itself.
            return 0, data, bufio.ErrFinalToken
        }   
        scanner.Split(onComma)
        // Scan.
        for scanner.Scan() {
            fmt.Printf("%q ", scanner.Text())
        }   
        if err := scanner.Err(); err != nil {
            fmt.Fprintln(os.Stderr, "reading input:", err)
        }   
    }
    
    

    交流学习

    上面两种方式都把编码时间写上,欢迎 v 贴出自己的方法,互相学习。

    github

    https://github.com/guonaihong/gout

    第 1 条附言  ·  2019-10-10 18:37:04 +08:00

    最后要flush数据,这是新的代码

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        const input = "1,2,3,4,5;6.7?8"
        var all []string
    
        prev, i := 0, 0
        for i = 0; i < len(input); i++ {
            switch input[i] {
            case ',', '.', ';', '?':
                all = append(all, input[prev:i+1])
                prev = i + 1
            }
        }
    
        if i-prev > 0 {
            all = append(all, input[prev:])
        }
    
        for _, v := range all {
            fmt.Printf("%s\n", v)
        }
    }
    
    9 条回复    2019-10-10 21:07:07 +08:00
    io123
        1
    io123  
       2019-10-10 09:46:00 +08:00 via Android
    果然还是 Py 大法好
    claysec
        2
    claysec  
       2019-10-10 10:34:30 +08:00   ❤️ 1
    @io123 +1 突然看着 go 的语法好迷啊。。
    T3RRY
        3
    T3RRY  
       2019-10-10 14:08:03 +08:00
    +1
    zhuzeitou
        4
    zhuzeitou  
       2019-10-10 14:37:15 +08:00   ❤️ 1
    第一段代码没处理遍历结束后剩余的最后一段内容……
    Biwood
        5
    Biwood  
       2019-10-10 15:05:59 +08:00
    package main

    import (
    "fmt"
    "regexp"
    "strings"
    )

    func main() {
    const input = "1,2,3,4,5;6.7?"
    re := regexp.MustCompile(`([,;\.\?])`)
    newStr := re.ReplaceAllString(input, "$1-")
    fmt.Printf("%q\n", strings.Split(newStr, "-"))
    }

    go 的正则没有后行断言,否则更简洁一些
    guonaihong
        6
    guonaihong  
    OP
       2019-10-10 18:24:27 +08:00
    @zhuzeitou 是的。马上改下。
    guonaihong
        7
    guonaihong  
    OP
       2019-10-10 18:34:18 +08:00
    @Biwood 这思路挺好。可以把-分割符换成不可见字符\x000(数字 0)
    reus
        8
    reus  
       2019-10-10 18:48:34 +08:00   ❤️ 1
    guonaihong
        9
    guonaihong  
    OP
       2019-10-10 21:07:07 +08:00
    @reus 可以可以。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5623 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 03:32 · PVG 11:32 · LAX 19:32 · JFK 22:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.