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语言使用select{}阻塞main函数介绍
Apr 25 Golang
go mod 安装依赖 unkown revision问题的解决方案
May 06 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
Golang使用Panic与Recover进行错误捕获
Mar 22 Golang
golang实现浏览器导出excel文件功能
Mar 25 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
Golang 实现WebSockets
Apr 24 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 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
url decode problem 解决方法
2011/12/26 PHP
php伪静态之APACHE篇
2014/06/02 PHP
PHP中仿制 ecshop验证码实例
2017/01/06 PHP
php学习笔记之字符串常见操作总结
2019/07/16 PHP
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
javascript获取dom的下一个节点方法
2014/09/05 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
js实现的牛顿摆效果
2015/03/31 Javascript
Jquery使用小技巧汇总
2015/12/29 Javascript
JavaScript兼容浏览器FF/IE技巧
2016/08/14 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
DOM事件探秘篇
2017/02/15 Javascript
基于Bootstrap模态对话框只加载一次 remote 数据的解决方法
2017/07/09 Javascript
基于jQuery实现图片推拉门动画效果的两种方法
2017/08/26 jQuery
将jquery.qqFace.js表情转换成微信的字符码
2017/12/01 jQuery
基于Vue的SPA动态修改页面title的方法(推荐)
2018/01/02 Javascript
JavaScript实现读取与输出XML文件数据的方法示例
2018/06/05 Javascript
React Native基础入门之调试React Native应用的一小步
2018/07/02 Javascript
js针对图片加载失败的处理方法分析
2019/08/24 Javascript
[56:01]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 Effect vs EG
2018/03/31 DOTA
将Python代码打包为jar软件的简单方法
2015/08/04 Python
Python编程实现双击更新所有已安装python模块的方法
2017/06/05 Python
Python实现单词翻译功能
2017/06/06 Python
Python 将pdf转成图片的方法
2018/04/23 Python
Python一句代码实现找出所有水仙花数的方法
2018/11/13 Python
Django CBV类的用法详解
2019/07/26 Python
python实现ftp文件传输系统(案例分析)
2020/03/20 Python
巴西购物网站:Submarino
2020/01/19 全球购物
一套PHP的笔试题
2013/05/31 面试题
孝敬父母的演讲稿
2014/05/14 职场文书
农村优秀教师事迹材料
2014/08/27 职场文书
购房协议书范本(无房产证)
2014/10/07 职场文书
村党支部书记个人对照材料汇报
2014/10/26 职场文书
2015年助理政工师工作总结
2015/05/26 职场文书
幼儿园开学家长寄语(2016春季)
2015/12/03 职场文书
读完《骆驼祥子》的观后感!
2019/07/05 职场文书