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各时间字符串使用解析
Apr 02 Golang
Go语言操作数据库及其常规操作的示例代码
Apr 21 Golang
golang 实现对Map进行键值自定义排序
Apr 28 Golang
对Golang中的FORM相关字段理解
May 02 Golang
Golang 编译成DLL文件的操作
May 06 Golang
Go 自定义package包设置与导入操作
May 06 Golang
go mod 安装依赖 unkown revision问题的解决方案
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
golang生成vcf通讯录格式文件详情
Mar 25 Golang
简单聊聊Golang中defer预计算参数
Mar 25 Golang
Go语言测试库testify使用学习
Jul 23 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
网页游戏开发入门教程二(游戏模式+系统)
2009/11/02 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
教你在PHPStorm中配置Xdebug
2015/07/27 PHP
php获取手机端的号码以及ip地址实例代码
2018/09/12 PHP
PHP simplexml_load_file()函数讲解
2019/02/03 PHP
PHP设计模式之迭代器模式Iterator实例分析【对象行为型】
2020/04/26 PHP
JavaScript高级程序设计
2006/12/29 Javascript
基于jquery的loading效果实现代码
2010/11/05 Javascript
基于jquery库的tab新形式使用
2012/11/16 Javascript
简略说明Javascript中的= =(等于)与= = =(全等于)区别
2013/04/16 Javascript
JavaScript instanceof 的使用方法示例介绍
2013/10/23 Javascript
JS实现在页面随时自定义背景颜色的方法
2015/02/27 Javascript
jQuery Dialog 取消右上角删除按钮事件
2016/09/07 Javascript
BootStrap组件之进度条的基本用法
2017/01/19 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
2017/08/17 Javascript
原生JS实现旋转轮播图+文字内容切换效果【附源码】
2018/09/29 Javascript
js使用swiper实现层叠轮播效果实例代码
2018/12/12 Javascript
详解vue中移动端自适应方案
2019/05/05 Javascript
vue项目中运用webpack动态配置打包多种环境域名的方法
2019/06/24 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
微信小程序语音同步智能识别的实现案例代码解析
2020/05/29 Javascript
详解Java中String JSONObject JSONArray List转换
2020/11/13 Javascript
小结Python用fork来创建子进程注意事项
2014/07/03 Python
Python绘制七段数码管实例代码
2017/12/20 Python
python实现切割url得到域名、协议、主机名等各个字段的例子
2019/07/25 Python
Python如何批量获取文件夹的大小并保存
2020/03/31 Python
Html5原创俄罗斯方块(基于canvas)
2019/01/07 HTML / CSS
英国豪华真皮和布艺沙发销售网站:Darlings of Chelsea
2018/01/05 全球购物
Overload和Override的区别
2012/09/02 面试题
护理专业毕业生自荐信范文
2014/01/05 职场文书
交通事故私了协议书
2014/04/16 职场文书
暑假学习心得体会
2014/09/02 职场文书
作文批改评语
2014/12/25 职场文书
python tkinter实现定时关机
2021/04/21 Python
浅谈CSS不规则边框的生成方案
2021/05/25 HTML / CSS
Java移除无效括号的方法实现
2021/08/07 Java/Android