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 Gin实现文件上传下载的示例代码
Apr 02 Golang
Go语言操作数据库及其常规操作的示例代码
Apr 21 Golang
解决Go gorm踩过的坑
Apr 30 Golang
对Golang中的FORM相关字段理解
May 02 Golang
Goland使用Go Modules创建/管理项目的操作
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
Go语言设计模式之结构型模式
Jun 22 Golang
golang为什么要统一错误处理
Apr 03 Golang
Golang MatrixOne使用介绍和汇编语法
Apr 19 Golang
Golang 实现WebSockets
Apr 24 Golang
GO中sync包自由控制并发示例详解
Aug 05 Golang
Go中使用gjson来操作JSON数据的实现
Aug 14 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
跟我学Laravel之快速入门
2014/10/15 PHP
PHP获取QQ达人QQ信息的方法
2015/03/05 PHP
微信公众平台之快递查询功能用法实例
2015/04/14 PHP
在php中设置session用memcache来存储的方法总结
2016/01/14 PHP
PHP引用返回用法示例
2016/05/28 PHP
PHP支付宝当面付2.0代码
2018/12/21 PHP
ie与ff下的event事件使用介绍
2013/11/25 Javascript
JS实现鼠标经过好友列表中的好友头像时显示资料卡的效果
2014/07/02 Javascript
js 通过cookie实现刷新不变化树形菜单
2014/10/30 Javascript
JavaScript闭包详解
2015/02/02 Javascript
Javascript中的arguments与重载介绍
2015/03/15 Javascript
JS实现网页每隔3秒弹出一次对话框的方法
2015/11/09 Javascript
下一代Bootstrap的5个特点 超酷炫!
2016/06/17 Javascript
微信小程序 后台登录(非微信账号)实例详解
2017/03/31 Javascript
vue实现todolist单页面应用
2017/04/11 Javascript
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
Vue 组件(component)教程之实现精美的日历方法示例
2018/01/08 Javascript
vue项目部署上线遇到的问题及解决方法
2018/06/10 Javascript
JS中数组与对象的遍历方法实例小结
2018/08/14 Javascript
基于vue-router 多级路由redirect 重定向的问题
2018/09/03 Javascript
webstorm中配置Eslint的两种方式及差异比较详解
2018/10/19 Javascript
js实现全选反选不选功能代码详解
2019/04/24 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
[03:41]DOTA2上海特锦赛小组赛第三日recap精彩回顾
2016/02/28 DOTA
[43:53]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第三场 8.22
2019/09/05 DOTA
Python中处理字符串的相关的len()方法的使用简介
2015/05/19 Python
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
Windows 下python3.8环境安装教程图文详解
2020/03/11 Python
Python计算指定日期是今年的第几天(三种方法)
2020/03/26 Python
pycharm实现print输出保存到txt文件
2020/06/01 Python
全球领先的在线cosplay服装商店:RoleCosplay
2020/01/18 全球购物
《雨点儿》教学反思
2014/04/14 职场文书
个人合作协议书范本
2014/04/18 职场文书
优秀学生党员先进事迹材料
2014/05/29 职场文书
2015年物业公司保洁工作总结
2015/10/22 职场文书
MySQL优化及索引解析
2022/03/17 MySQL