• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    golang正则之命名分组方式

    正则中有分组这个功能,在golang中也可以使用命名分组。

    一次匹配的情况

    场景还原如下:

    有一行文本,格式为:姓名 年龄 邮箱地址

    请将其转换为一个map

    代码实现如下:

    str := `Alice 20 alice@gmail.com`
    // 使用命名分组,显得更清晰
    re := regexp.MustCompile(`(?Pname>[a-zA-Z]+)\s+(?Page>\d+)\s+(?Pemail>\w+@\w+(?:\.\w+)+)`)
    match := re.FindStringSubmatch(str)
    groupNames := re.SubexpNames()
    fmt.Printf("%v, %v, %d, %d\n", match, groupNames, len(match), len(groupNames))
    result := make(map[string]string)
    // 转换为map
    for i, name := range groupNames {
        if i != 0  name != "" { // 第一个分组为空(也就是整个匹配)
            result[name] = match[i]
        }
    }
    prettyResult, _ := json.MarshalIndent(result, "", "  ")
    fmt.Printf("%s\n", prettyResult)

    输出为:

    [Alice 20 alice@gmail.com Alice 20 alice@gmail.com], [ name age email], 4, 4
    {
      "age": "20",
      "email": "alice@gmail.com",
      "name": "Alice"
    }

    注意 [ name age email]有4个元素, 第一个为""。

    多次匹配的情况

    接上面的例子,实现一个更贴近现实的需求:

    有一个文件, 内容大致如下:

    Alice 20 alice@gmail.com
    Bob 25 bob@outlook.com
    gerrylon 26 gerrylon@github.com
    ...
    更多内容

    和上面一样, 不过这次转出来是一个slice of map, 也就是多个map。

    代码如下:

    // 文件内容直接用字符串表示
    usersStr := `
        Alice 20 alice@gmail.com
        Bob 25 bob@outlook.com
        gerrylon 26 gerrylon@github.com
    `
    userRe := regexp.MustCompile(`(?Pname>[a-zA-Z]+)\s+(?Page>\d+)\s+(?Pemail>\w+@\w+(?:\.\w+)+)`)
    // 这里要用FindAllStringSubmatch,找到所有的匹配
    users := userRe.FindAllStringSubmatch(usersStr, -1)
    groupNames := userRe.SubexpNames()
    var result []map[string]string // slice of map
    // 循环所有行
    for _, user := range users {
        m := make(map[string]string)
        // 对每一行生成一个map
        for j, name := range groupNames {
            if j != 0  name != "" {
                m[name] = strings.TrimSpace(user[j])
            }
        }
        result = append(result, m)
    }
    prettyResult, _ := json.MarshalIndent(result, "", "  ")
    fmt.Println(string(prettyResult))

    输出为:

    [
      {
        "age": "20",
        "email": "alice@gmail.com",
        "name": "Alice"
      },
      {
        "age": "25",
        "email": "bob@outlook.com",
        "name": "Bob"
      },
      {
        "age": "26",
        "email": "gerrylon@github.com",
        "name": "gerrylon"
      }
    ]

    总结

    使用命名分组可以使正则表示的意义更清晰。

    转换为map更加符合人类的阅读习惯,不过比一般的根据索引取分组值麻烦一些。

    补充:golang 正则分组匹配多个值

    看代码吧~

    import (
       "encoding/json"
       "fmt"
       "regexp"
    )
    str := `9x_xx:995:88`  // `9x_xx:995`
    // 使用命名分组,一次匹配多个值
    re := regexp.MustCompile(`(?Pfname>\w+):+(?Pmod>[1-9]*):*(?Pstrlen>[0-9]*)`)
    match := re.FindStringSubmatch(str)
    groupNames := re.SubexpNames()
    fmt.Printf("%v, %v, %d, %d\n", match, groupNames, len(match), len(groupNames))
     
    result := make(map[string]string)
    if len(match) == len(groupNames) {
       // 转换为map
       for i, name := range groupNames {
          if i != 0  name != "" { // 第一个分组为空(也就是整个匹配)
             result[name] = match[i]
          }
       }
    }
    prettyResult, _ := json.MarshalIndent(result, "", "  ") 
    fmt.Printf("%s\n", prettyResult)

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • 基于golang中container/list包的用法说明
    • Golang中List的实现方法示例详解
    • golang使用grpc+go-kit模拟oauth认证的操作
    • golang中for range的取地址操作陷阱介绍
    • golang如何去除多余空白字符(含制表符)
    • 用golang如何替换某个文件中的字符串
    • 解决golang中container/list包中的坑
    上一篇:Golang 正则匹配效率详解
    下一篇:用golang如何替换某个文件中的字符串
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    golang正则之命名分组方式 golang,正则,之,命名,分组,