golang正则之命名分组方式


Posted in Golang onApril 25, 2021

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

一次匹配的情况

场景还原如下:

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

请将其转换为一个map

代码实现如下:

str := `Alice 20 alice@gmail.com`
// 使用命名分组,显得更清晰
re := regexp.MustCompile(`(?P<name>[a-zA-Z]+)\s+(?P<age>\d+)\s+(?P<email>\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(`(?P<name>[a-zA-Z]+)\s+(?P<age>\d+)\s+(?P<email>\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(`(?P<fname>\w+):+(?P<mod>[1-9]*):*(?P<strlen>[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 相关文章推荐
Go缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
golang中的空slice案例
Apr 27 Golang
golang http使用踩过的坑与填坑指南
Apr 27 Golang
golang 实现Location跳转方式
May 02 Golang
完美解决golang go get私有仓库的问题
May 05 Golang
Golang之sync.Pool使用详解
May 06 Golang
解决golang 关于全局变量的坑
May 06 Golang
Go语言基础map用法及示例详解
Nov 17 Golang
Go语言安装并操作redis的go-redis库
Apr 14 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
Go语言怎么使用变长参数函数
Jul 15 Golang
go语言-在mac下brew升级golang
Apr 25 #Golang
go原生库的中bytes.Buffer用法
Apr 25 #Golang
Go缓冲channel和非缓冲channel的区别说明
Apr 25 #Golang
Go语言使用select{}阻塞main函数介绍
win10下go mod配置方式
Go语言-为什么返回值为接口类型,却返回结构体
Apr 24 #Golang
go:垃圾回收GC触发条件详解
Apr 24 #Golang
You might like
压力如何影响浓缩咖啡品质
2021/03/03 咖啡文化
开发大型PHP项目的方法
2006/10/09 PHP
PHP学习之输出字符串(echo,print,printf,print_r和var_dump)
2011/04/17 PHP
jscript之List Excel Color Values
2007/06/13 Javascript
JavaScript setTimeout和setInterval的使用方法 说明
2010/03/25 Javascript
javascript面向对象之二 命名空间
2011/02/08 Javascript
javaScript复制功能调用实现方案
2012/12/13 Javascript
JS兼容浏览器的导出Excel(CSV)文件的方法
2014/05/03 Javascript
jQuery循环滚动新闻列表示例代码
2014/06/17 Javascript
深入学习JavaScript中的原型prototype
2015/08/13 Javascript
JavaScript中this详解
2015/09/01 Javascript
javascript日期格式化方法汇总
2015/10/04 Javascript
基于jquery实现左右按钮点击的图片切换效果
2021/01/27 Javascript
javascript实现简易计算器
2017/02/01 Javascript
详解react-router如何实现按需加载
2017/06/15 Javascript
js分页之前端代码实现和请求处理
2017/08/04 Javascript
一步步教你利用Docker设置Node.js
2018/11/20 Javascript
vue使用vuex实现首页导航切换不同路由的方法
2019/05/08 Javascript
layerui代码控制tab选项卡,添加,关闭的实例
2019/09/04 Javascript
解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)
2020/05/03 Javascript
python通过opencv实现批量剪切图片
2017/11/13 Python
Python实现的读取电脑硬件信息功能示例
2018/05/30 Python
Python爬虫实现简单的爬取有道翻译功能示例
2018/07/13 Python
python3 读取Excel表格中的数据
2018/10/16 Python
对python mayavi三维绘图的实现详解
2019/01/08 Python
在python带权重的列表中随机取值的方法
2019/01/23 Python
python使用if语句实现一个猜拳游戏详解
2019/08/27 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
如何现实servlet的单线程模式
2014/08/05 面试题
装修设计师求职信
2014/02/26 职场文书
办公室文员岗位职责范本
2014/06/12 职场文书
2014最新离职证明范本
2014/09/12 职场文书
2014年行政人事工作总结
2014/12/09 职场文书
岗位聘任报告
2015/03/02 职场文书
党支部工作总结2015
2015/04/01 职场文书
深入解析NumPy中的Broadcasting广播机制
2021/05/30 Python