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中切片copy复制和等号复制的区别介绍
Apr 27 Golang
解决Golang中ResponseWriter的一个坑
Apr 27 Golang
彻底理解golang中什么是nil
Apr 29 Golang
解决golang post文件时Content-Type出现的问题
May 02 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
go 实现简易端口扫描的示例
May 22 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
Golang并发操作中常见的读写锁详析
Aug 30 Golang
golang定时器
Apr 14 Golang
Golang 对es的操作实例
Apr 20 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 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接收POST数据,解析json数据
2013/06/28 PHP
PHP中把对象转换为关联数组代码分享
2015/04/09 PHP
PHP+Ajax实现无刷新分页实例详解(附demo源码下载)
2016/04/07 PHP
PHP常用字符串函数用法实例总结
2020/06/04 PHP
Extjs中DisplayField的日期或者数字格式化扩展
2010/09/03 Javascript
关于jquery.validate1.9.0前台验证的使用介绍
2013/04/26 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
JavaScript中的Repaint和Reflow用法详解
2015/07/27 Javascript
JQuery菜单效果的两个实例讲解(3)
2015/09/17 Javascript
简单的jQuery banner图片轮播实例代码
2016/03/04 Javascript
第一次接触JS require.js模块化工具
2016/04/17 Javascript
jquery获取所有选中的checkbox实现代码
2016/05/26 Javascript
JS 调试中常见的报错问题解决方法
2017/05/20 Javascript
在vue中实现简单页面逆传值的方法
2017/11/27 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
vue项目打包后上传至GitHub并实现github-pages的预览
2019/05/06 Javascript
Vue 2.0 侦听器 watch属性代码详解
2019/06/19 Javascript
vue实现权限控制路由(vue-router 动态添加路由)
2019/11/04 Javascript
解决vue自定义指令导致的内存泄漏问题
2020/08/04 Javascript
浅谈vue项目,访问路径#号的问题
2020/08/14 Javascript
[00:10]DOTA2 TI9勇士令状明日上线
2019/05/07 DOTA
浅谈python实现Google翻译PDF,解决换行的问题
2018/11/28 Python
matplotlib.pyplot绘图显示控制方法
2019/01/15 Python
Python3 max()函数基础用法
2019/02/19 Python
Python 使用PyQt5 完成选择文件或目录的对话框方法
2019/06/27 Python
python-序列解包(对可迭代元素的快速取值方法)
2019/08/24 Python
matplotlib grid()设置网格线外观的实现
2021/02/22 Python
html5+CSS3+JS实现七夕言情功能代码
2017/08/28 HTML / CSS
成龙霸王洗发水广告词
2014/03/14 职场文书
社区食品安全实施方案
2014/03/28 职场文书
学雷锋月活动总结
2014/04/25 职场文书
党支部四风整改方案
2014/10/25 职场文书
幼儿园小班见习报告
2014/10/31 职场文书
现实表现材料范文
2014/12/23 职场文书
公司停电通知
2015/04/15 职场文书
Apache POI的基本使用详解
2021/11/07 Servers