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原生库的中bytes.Buffer用法
Apr 25 Golang
goland 恢复已更改文件的操作
Apr 28 Golang
golang json数组拼接的实例
Apr 28 Golang
彻底理解golang中什么是nil
Apr 29 Golang
解决Goland 同一个package中函数互相调用的问题
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
Golang 获取文件md5校验的方法以及效率对比
May 08 Golang
go语言基础 seek光标位置os包的使用
May 09 Golang
浅谈GO中的Channel以及死锁的造成
Mar 18 Golang
Golang 字符串的常见操作
Apr 19 Golang
Golang实现可重入锁的示例代码
May 25 Golang
GoFrame框架数据校验之校验结果Error接口对象
Jun 21 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
无限级别菜单的实现
2006/10/09 PHP
PHP脚本数据库功能详解(上)
2006/10/09 PHP
PHP生成静态页面详解
2006/11/19 PHP
smarty模板嵌套之include与fetch性能测试
2010/12/05 PHP
phpstudy的php版本自由修改的方法
2017/10/18 PHP
PHP扩展类型及安装方式解析
2020/04/27 PHP
JavaScript下利用fso判断文件是否存在的代码
2010/12/11 Javascript
js获取select标签的值且兼容IE与firefox
2013/12/30 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
2016/05/31 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
深入浅析angular和vue还有jquery的区别
2018/08/13 jQuery
4个顶级JavaScript高级文本编辑器
2018/10/10 Javascript
Vue.js 中的 v-cloak 指令及使用详解
2018/11/19 Javascript
详解vue引入子组件方法
2019/02/12 Javascript
详解小程序用户登录状态检查与更新实例
2019/05/15 Javascript
elementUI 动态生成几行几列的方法示例
2019/07/11 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
vue列表数据发生变化指令没有更新问题及解决方法
2020/01/16 Javascript
一文读懂vue动态属性数据绑定(v-bind指令)
2020/07/20 Javascript
js实现简单抽奖功能
2020/11/24 Javascript
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
python中模块的__all__属性详解
2017/10/26 Python
python redis 批量设置过期key过程解析
2019/11/26 Python
在PyTorch中使用标签平滑正则化的问题
2020/04/03 Python
python中最小二乘法详细讲解
2021/02/19 Python
Schutz鞋官方网站:Schutz Shoes
2017/12/13 全球购物
促销活动方案模板
2014/02/24 职场文书
机电一体化求职信
2014/03/10 职场文书
世博会口号
2014/06/20 职场文书
医德医风自我评价
2014/09/19 职场文书
2015年转正工作总结范文
2015/04/02 职场文书
《兰兰过桥》教学反思
2016/02/20 职场文书
python flask开发的简单基金查询工具
2021/06/02 Python
Java实现聊天机器人完善版
2021/07/04 Java/Android
PostgreSQL聚合函数介绍以及分组和排序
2022/04/12 PostgreSQL
Mysql 数据库中的 redo log 和 binlog 写入策略
2022/04/26 MySQL