为了账号安全,请及时绑定邮箱和手机立即绑定

通过正则表达式拆分输入字符串

通过正则表达式拆分输入字符串

Go
元芳怎么了 2023-05-08 14:39:48
如何在 Go 中通过正则表达式拆分下面的输入字符串?字符串示例:我知道如何按点拆分,但如何避免在引号中拆分?"a.b.c.d" -> ["a", "b", "c", "d"]"a."b.c".d" -> ["a", "b.c", "d"]"a.'b.c'.d" -> ["a", "b.c", "d"]
查看完整描述

3 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

这是另一个选项,它的正则表达式不那么复杂。它使用垃圾桶技巧。所以真正的数据在(第一和第二)捕获组上。

它甚至适用于像这样的嵌套引号:"a.'b.c'.d.e."f.g.h""只要没有 2 级或更多级别的递归(如此处:"a.'b."c.d"'",引号内引号内引号)。

正则表达式是这样的:^"|['"](\w+(?:\.\w+)*)['"]|(\w+)

和代码:

package main


import (

    "regexp"

    "fmt"

)


func main() {

    var re = regexp.MustCompile(`^"|['"](\w+(?:\.\w+)*)['"]|(\w+)`)

    var str = `"a.'b.c'.d.e."f.g.h""`


    result := re.FindAllStringSubmatch(str, -1)

    for _, m := range result {

        if (m[1] != "" || m[2] != "") {

            fmt.Print(m[1] + m[2] + "\n")

        }

    }

}

输入:


"a.'b.c'.d.e."f.g.h""


输出:


a

b.c

d

e

f.g.h



查看完整回答
反对 回复 2023-05-08
?
Helenr

TA贡献1780条经验 获得超3个赞

匹配平衡定界符对于正则表达式来说是一个复杂的问题,除非你使用类似Go pcre package 的东西。

相反,可以修改Go CSV 解析器。将其配置为用作.分隔符、惰性引号(CSV 引号为')和可变长度记录。

package main


import (

    "encoding/csv"

    "fmt"

    "io"

    "log"

    "strings"

)


func main() {

    lines := `a.b.c.d

a.\"b.c\".d

a.'b.c'.d

`


    csv := csv.NewReader(strings.NewReader(lines))

    csv.Comma = '.'

    csv.LazyQuotes = true

    csv.FieldsPerRecord = -1

    for {

        record, err := csv.Read()

        if err == io.EOF {

            break

        }

        if err != nil {

            log.Fatal(err)

        }


        fmt.Printf("%#v\n", record)

    }

}


查看完整回答
反对 回复 2023-05-08
?
BIG阳

TA贡献1859条经验 获得超6个赞

由于 go 不支持否定前瞻,我认为找到与.您要拆分的正则表达式相匹配的正则表达式并不容易/可能。相反,您可以匹配周围的文本并仅适当地捕获:

所以正则表达式本身有点难看,但这是细分(忽略转义字符):

(\'[^.'"]+(?:\.[^.'"]+)+\')|(\"[^.'"]+(?:\.[^.'"]+)+\")|(?:([^.'"]+)\.?)|(?:\.([^.'\"]+))

此正则表达式匹配四种情况,并捕获这些匹配的某些子集:

  • (\'[^.'"]+(?:\.[^.'"]+)+\')- 匹配和捕获单引号文本

    • \'-'逐字匹配

    • [^.'"]+- 匹配非行号和非句点的序列

    • (?:\.[^.'"]+)+- 匹配句点后跟一系列非引号和非句点,根据需要重复多次。没有被捕获。

    • \'-'逐字匹配

  • (\"[^.'"]+(?:\.[^.'"]+)+\")- 匹配和捕获双引号文本

    • 与上面相同,但带有双引号

  • (?:([^.'"]+)\.?)- 匹配由可选 开始的文本.,不捕获.

    • ([^.'"]+)- 匹配和捕获非报价和非句点的序列

    • \.?- 可选择匹配一个句点(可选择捕获最后一位分隔文本)

  • (?:\.([^.'"]+))- 匹配前面有 a 的文本.,不捕获.

    • 与上面相同,但句点在捕获组之前,也是非可选的

转储捕获的示例代码:

package main


import (

    "fmt"

    "regexp"

)


func main() {

    re := regexp.MustCompile("('[^.'\"]+(?:\\.[^.'\"]+)+')|(\"[^.'\"]+(?:\\.[^.'\"]+)+\")|(?:([^.'\"]+)\\.?)|(?:\\.([^.'\"]+))")

    txt := "a.b.c.'d.e'"


    result:= re.FindAllStringSubmatch(txt, -1)


    for k, v := range result {

        fmt.Printf("%d. %s\n", k, v)

    }

}


查看完整回答
反对 回复 2023-05-08
  • 3 回答
  • 0 关注
  • 119 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信