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 相关文章推荐
解决golang结构体tag编译错误的问题
May 02 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
Golang二维数组的使用方式
May 28 Golang
Go遍历struct,map,slice的实现
Jun 13 Golang
Golang的继承模拟实例
Jun 30 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
Golang 对es的操作实例
Apr 20 Golang
Golang bufio详细讲解
Apr 21 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Golang gRPC HTTP协议转换示例
Jun 16 Golang
在ubuntu下安装go开发环境的全过程
Aug 05 Golang
Go gorilla/sessions库安装使用
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中通过ADO调用Asscess数据库和COM程序
2006/10/09 PHP
php面向对象全攻略 (十七) 自动加载类
2009/09/30 PHP
jquery获取多个checkbox的值异步提交给php的方法
2015/06/24 PHP
php将html转成wml的WAP标记语言实例
2015/07/08 PHP
设置下载不需要倒计时cookie(倒计时代码)
2008/11/19 Javascript
基于jquery的气泡提示效果
2010/05/31 Javascript
判断ie的两种简单方法
2013/08/12 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
jquery判断单选按钮radio是否选中的方法
2015/05/05 Javascript
举例说明JavaScript中的实例对象与原型对象
2016/03/11 Javascript
高效利用Angular中内置服务$http、$location等
2016/03/22 Javascript
jquery实现上传文件大小类型的验证例子(推荐)
2016/06/25 Javascript
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
React Native使用百度Echarts显示图表的示例代码
2017/11/07 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
jQuery实现获取动态添加的标签对象示例
2018/06/28 jQuery
使用layer弹窗和layui表单实现新增功能
2018/08/09 Javascript
Vue+webpack项目配置便于维护的目录结构教程详解
2018/10/14 Javascript
Layer UI表格列日期格式化及取消自动填充日期的实现方法
2020/05/10 Javascript
python实现的文件同步服务器实例
2015/06/02 Python
详解Python中heapq模块的用法
2016/06/28 Python
基于TensorFlow中自定义梯度的2种方式
2020/02/04 Python
pytorch使用horovod多gpu训练的实现
2020/09/09 Python
scrapy在python爬虫中搭建出错的解决方法
2020/11/22 Python
python里glob模块知识点总结
2021/01/05 Python
前端水印的简单实现代码示例
2020/12/02 HTML / CSS
Dyson戴森波兰官网:Dyson.pl
2019/08/05 全球购物
软件测试英文面试题
2012/10/14 面试题
保安拾金不昧表扬信
2014/01/15 职场文书
党员干部公开承诺书
2014/03/26 职场文书
岗位工作说明书
2014/07/29 职场文书
企业财务总监岗位职责
2015/04/03 职场文书
化工厂员工工作总结
2015/10/15 职场文书
企业愿景口号
2015/12/25 职场文书
CSS 实现Chrome标签栏的技巧
2021/08/04 HTML / CSS
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python