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语言中切片与内存复制 memcpy 的实现操作
Apr 27 Golang
golang json数组拼接的实例
Apr 28 Golang
golang 生成对应的数据表struct定义操作
Apr 28 Golang
Go语言中break label与goto label的区别
Apr 28 Golang
Golang之sync.Pool使用详解
May 06 Golang
Go 在 MongoDB 中常用查询与修改的操作
May 07 Golang
基于Golang 高并发问题的解决方案
May 08 Golang
go 实现简易端口扫描的示例
May 22 Golang
golang中字符串MD5生成方式总结
Jul 04 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
深入理解go缓存库freecache的使用
Feb 15 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 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
是否存在第一台收音机的说法
2021/03/01 无线电
图书管理程序(二)
2006/10/09 PHP
PHP4 与 MySQL 数据库操作函数详解
2006/12/06 PHP
php从右向左/从左向右截取字符串的实现方法
2011/11/28 PHP
解析php获取字符串的编码格式的方法(函数)
2013/06/21 PHP
php获取文章上一页与下一页的方法
2014/12/01 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
PHP查找一列有序数组是否包含某值的方法
2020/02/07 PHP
javascript判断是否按回车键并解决浏览器之间的差异
2014/05/13 Javascript
防止登录页面出现在frame中js代码
2014/07/22 Javascript
Jquery实现图片预加载与延时加载的方法
2014/12/22 Javascript
javascript自动生成包含数字与字符的随机字符串
2015/02/09 Javascript
Bootstrap导航条学习使用(一)
2017/02/08 Javascript
JS中数组与对象的遍历方法实例小结
2018/08/14 Javascript
前端Electron新手入门教程详解
2019/06/21 Javascript
Python中__call__用法实例
2014/08/29 Python
Python 用Redis简单实现分布式爬虫的方法
2017/11/23 Python
Tensorflow中使用tfrecord方式读取数据的方法
2018/06/19 Python
python+influxdb+shell编写区域网络状况表
2018/07/27 Python
对python 多线程中的守护线程与join的用法详解
2019/02/18 Python
用python写一个定时提醒程序的实现代码
2019/07/22 Python
在python image 中安装中文字体的实现方法
2019/08/22 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
英国现代绅士品牌:Hackett
2017/12/17 全球购物
三星加拿大官方网上商店:Samsung CA
2020/12/18 全球购物
Happy Plugs官网:瑞典无线耳机品牌
2020/07/16 全球购物
幼儿园优秀班主任事迹材料
2014/05/14 职场文书
公司大门门卫岗位职责
2014/06/11 职场文书
合伙经营协议书范本(通用版)
2014/12/03 职场文书
幼儿园母亲节活动总结
2015/02/10 职场文书
百家讲坛观后感
2015/06/12 职场文书
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
Python使用UDP实现720p视频传输的操作
2021/04/24 Python
CSS的class与id常用的命名规则
2021/05/18 HTML / CSS
html+css实现分层金字塔的实例
2021/06/02 HTML / CSS