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 正则匹配效率详解
Apr 25 Golang
Golang 如何实现函数的任意类型传参
Apr 29 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
golang 比较浮点数的大小方式
May 02 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
Golang 语言控制并发 Goroutine的方法
Jun 30 Golang
入门学习Go的基本语法
Jul 07 Golang
GO语言异常处理分析 err接口及defer延迟
Apr 14 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Golang并发工具Singleflight
May 06 Golang
GoFrame框架数据校验之校验结果Error接口对象
Jun 21 Golang
Go本地测试解耦任务拆解及沟通详解Go本地测试的思路沟通的重要性总结
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
PHP新手上路(八)
2006/10/09 PHP
php 引用(&amp;)详解
2009/11/20 PHP
如何解决PHP使用mysql_query查询超大结果集超内存问题
2016/03/14 PHP
php rsa 加密,解密,签名,验签详解
2016/12/06 PHP
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
2012/10/11 Javascript
javascript通过navigator.userAgent识别各种浏览器
2013/10/25 Javascript
thinkphp 表名 大小写 窍门
2015/02/01 Javascript
JavaScript中的substr()方法使用详解
2015/06/06 Javascript
基于jquery实现省市联动特效
2015/12/17 Javascript
ECHO.js 纯javascript轻量级延迟加载的实例代码
2016/05/24 Javascript
浅谈Jquery中Ajax异步请求中的async参数的作用
2016/06/06 Javascript
AngularJS入门教程之Select(选择框)详解
2016/07/27 Javascript
完美解决jQuery符号$与其他javascript 库、框架冲突的问题
2016/08/09 Javascript
微信小程序 合法域名校验出错详解及解决办法
2017/03/09 Javascript
Angular.JS中指令ng-if的注意事项小结
2017/06/21 Javascript
JS同步、异步、延迟加载的方法
2018/05/05 Javascript
Python 过滤字符串的技巧,map与itertools.imap
2008/09/06 Python
在Python中用has_key()方法查找键是否存在的教程
2015/05/21 Python
python开发之for循环操作实例详解
2015/11/12 Python
python实现词法分析器
2019/01/31 Python
python pygame实现球球大作战
2019/11/25 Python
linux环境下安装python虚拟环境及注意事项
2020/01/07 Python
python tqdm库的使用
2020/11/30 Python
CSS3中设置3D变形的transform-style属性详解
2016/05/23 HTML / CSS
荷兰照明、灯具和配件网上商店:dmlights
2019/08/25 全球购物
接口可以包含哪些成员
2012/09/30 面试题
北京捷通华声语音技术有限公司Java软件工程师笔试题
2012/04/10 面试题
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
单位实习证明怎么写
2014/01/17 职场文书
学校感恩教育活动总结
2014/07/07 职场文书
危货运输企业安全生产责任书
2014/07/28 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
超市店长竞聘书
2015/09/15 职场文书
美德少年事迹材料(2016推荐版)
2016/02/25 职场文书
Redis安装启动及常见数据类型
2021/04/14 Redis
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
2022/06/14 Golang