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语言map与string的相互转换的实现
Apr 07 Golang
golang中的空slice案例
Apr 27 Golang
golang http使用踩过的坑与填坑指南
Apr 27 Golang
golang 实现菜单树的生成方式
Apr 28 Golang
使用Golang的channel交叉打印两个数组的操作
Apr 29 Golang
Golang 实现获取当前函数名称和文件行号等操作
May 08 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
Go语言特点及基本数据类型使用详解
Mar 21 Golang
Golang入门之计时器
May 04 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
Go gorilla securecookie库的安装使用详解
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
php ci框架验证码实例分析
2013/06/26 PHP
php获取字段名示例分享
2014/03/03 PHP
php制作文本式留言板
2015/03/18 PHP
php实现背景图上添加圆形logo图标的方法
2016/11/17 PHP
PHP实现下载远程图片保存到本地的方法
2017/06/19 PHP
JS 两个字符串时间的天数差计算
2013/08/25 Javascript
jquery使用ul模拟select实现表单美化的方法
2015/08/18 Javascript
JavaScript类型系统之Object详解
2016/01/07 Javascript
浅谈js和css内联外联注意事项
2016/06/30 Javascript
vuejs指令详解
2017/02/07 Javascript
深入理解nodejs中Express的中间件
2017/05/19 NodeJs
vue中使用refs定位dom出现undefined的解决方法
2017/12/21 Javascript
vue 添加和编辑用同一个表单,el-form表单提交后清空表单数据操作
2020/08/03 Javascript
原生JavaScript实现幻灯片效果
2021/02/19 Javascript
详解Vue3.0 + TypeScript + Vite初体验
2021/02/22 Vue.js
[03:58]兄弟们,回来开黑了!DOTA2昔日战友招募宣传视频
2016/07/17 DOTA
[55:25]2018DOTA2亚洲邀请赛3月29日 小组赛A组 VG VS OG
2018/03/30 DOTA
[05:37]DOTA2-DPC中国联赛 正赛 Elephant vs iG 选手采访
2021/03/11 DOTA
Flask框架的学习指南之用户登录管理
2016/11/20 Python
深入理解Python中range和xrange的区别
2017/11/26 Python
Python + selenium + requests实现12306全自动抢票及验证码破解加自动点击功能
2018/11/23 Python
Python两台电脑实现TCP通信的方法示例
2019/05/06 Python
python3中datetime库,time库以及pandas中的时间函数区别与详解
2020/04/16 Python
python使用建议与技巧分享(一)
2020/08/17 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
意大利时尚奢侈品店:D’Aniello Boutique
2021/01/19 全球购物
采购主管工作职责
2013/12/12 职场文书
四川成都导游欢迎词
2014/01/18 职场文书
大学生水果店创业计划书
2014/01/28 职场文书
管理提升方案
2014/06/04 职场文书
廉政教育的心得体会
2014/09/01 职场文书
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
地方白酒代理协议书
2014/10/25 职场文书
2014年药店工作总结
2014/11/20 职场文书
2016年度农村党员干部主题教育活动总结
2016/04/06 职场文书
python办公自动化之excel的操作
2021/05/23 Python