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

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

  •  
  •   guonaihong · 13 天前 · 894 次点击

    开发过程中少不了要于字符串打交道。假如要对一个文本串进行分段,分割符是.?;. 还要保留分割符号,就不能使用常用的 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 条附言  ·  12 天前

    最后要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
        1
    io123   13 天前 via Android
    果然还是 Py 大法好
        2
    claysec   13 天前   ♥ 1
    @io123 +1 突然看着 go 的语法好迷啊。。
        3
    T3RRY   13 天前
    +1
        4
    zhuzeitou   13 天前   ♥ 1
    第一段代码没处理遍历结束后剩余的最后一段内容……
        5
    Biwood   13 天前
    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 的正则没有后行断言,否则更简洁一些
        6
    guonaihong   12 天前
    @zhuzeitou 是的。马上改下。
        7
    guonaihong   12 天前
    @Biwood 这思路挺好。可以把-分割符换成不可见字符\x000(数字 0)
        8
    reus   12 天前   ♥ 1
        9
    guonaihong   12 天前
    @reus 可以可以。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3860 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 25ms · UTC 09:53 · PVG 17:53 · LAX 02:53 · JFK 05:53
    ♥ Do have faith in what you're doing.