【问题标题】:Split string along regex, but keep matches沿正则表达式拆分字符串,但保持匹配
【发布时间】:2019-11-28 23:29:02
【问题描述】:

我想按正则表达式拆分字符串,但保留匹配项。

我尝试在正则表达式上拆分字符串,但它会丢弃匹配项。我也尝试过使用this,但我不太擅长将代码从一种语言翻译到另一种语言,更不用说C#了。

re := regexp.MustCompile(`\d`)
array := re.Split("ab1cd2ef3", -1)

我需要数组的值是["ab", "1", "cd", "2", "ef", "3"],但是数组的值是["ab", "cd ", "ef"]。没有错误。

【问题讨论】:

    标签: string go split


    【解决方案1】:

    您在链接中指出的那种正则表达式支持在 Go 正则表达式包中不可用。您可以阅读related discussion

    您想要达到的目标(根据给出的示例)可以使用正则表达式来匹配数字或非数字。

    package main
    
    import (
        "fmt"
        "regexp"
    )
    
    func main() {
        str := "ab1cd2ef3"
        r := regexp.MustCompile(`(\d|[^\d]+)`)
        fmt.Println(r.FindAllStringSubmatch(str, -1))
    }
    

    游乐场:https://play.golang.org/p/L-ElvkDky53

    输出:

    [[ab ab] [1 1] [cd cd] [2 2] [ef ef] [3 3]]
    

    【讨论】:

    • 我可以对多个分隔符做同样的事情吗?好像我做不到。 ( \(\)|[^ \(\)]+)
    • 它只是匹配令牌的正则表达式。因此,只要您可以使用正则表达式单独表示令牌,您就可以使用| 分隔多个令牌。如果你能提供一些示例字符串,会更容易理解。
    【解决方案2】:

    我认为当前的 regexp 包不可能做到这一点,但 Split 可以很容易地扩展到这种行为。

    这应该适用于您的情况:

    func Split(re *regexp.Regexp, s string, n int) []string {
        if n == 0 {
            return nil
        }
    
        matches := re.FindAllStringIndex(s, n)
        strings := make([]string, 0, len(matches))
    
        beg := 0
        end := 0
        for _, match := range matches {
            if n > 0 && len(strings) >= n-1 {
                break
            }
    
            end = match[0]
            if match[1] != 0 {
                strings = append(strings, s[beg:end])
            }
            beg = match[1]
            // This also appends the current match
            strings = append(strings, s[match[0]:match[1]])
        }
    
        if end != len(s) {
            strings = append(strings, s[beg:])
        }
    
        return strings
    }
    
    

    【讨论】:

      【解决方案3】:

      愚蠢的解决方案。在字符串中添加分隔符,并用分隔符分割。

      package main
      
      import (
          "fmt"
          "regexp"
          "strings"
      )
      
      func main() {
          re := regexp.MustCompile(`\d+`)
          input := "ab1cd2ef3"
          sep := "|"
      
          indexes := re.FindAllStringIndex(input, -1)
          fmt.Println(indexes)
      
          move := 0
          for _, v := range indexes {
              p1 := v[0] + move
              p2 := v[1] + move
              input = input[:p1] + sep + input[p1:p2] + sep + input[p2:]
              move += 2
          }
      
          result := strings.Split(input, sep)
      
          fmt.Println(result)
      }
      

      【讨论】:

        【解决方案4】:

        您可以使用bufio.Scanner

        package main
        
        import (
           "bufio"
           "strings"
        )
        
        func digit(data []byte, eof bool) (int, []byte, error) {
           for i, b := range data {
              if '0' <= b && b <= '9' {
                 if i > 0 {
                    return i, data[:i], nil
                 }
                 return 1, data[:1], nil
              }
           }
           return 0, nil, nil
        }
        
        func main() {
           s := bufio.NewScanner(strings.NewReader("ab1cd2ef3"))
           s.Split(digit)
           for s.Scan() {
              println(s.Text())
           }
        }
        

        https://golang.org/pkg/bufio#Scanner.Split

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-09
          • 2011-02-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-17
          • 2022-10-04
          相关资源
          最近更新 更多