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
基于Go Int转string几种方式性能测试
Apr 28 Golang
golang 接口嵌套实现复用的操作
Apr 29 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
golang 实现时间戳和时间的转化
May 07 Golang
Golang的继承模拟实例
Jun 30 Golang
Go Plugins插件的实现方式
Aug 07 Golang
Go 语言中 20 个占位符的整理
Oct 16 Golang
Go语言基础切片的创建及初始化示例详解
Nov 17 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Golang解析JSON对象
Apr 30 Golang
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命令行用法入门实例教程
2014/10/27 PHP
Zend Framework教程之路由功能Zend_Controller_Router详解
2016/03/07 PHP
Zend Framework教程之Zend_Db_Table_Row用法实例分析
2016/03/21 PHP
php字符串比较函数用法小结(strcmp,strcasecmp,strnatcmp及strnatcasecmp)
2016/07/18 PHP
PHP工厂模式的日常使用
2019/03/20 PHP
Laravel如何同时连接多个数据库详解
2019/08/13 PHP
jQuery EasyUI API 中文文档 - Documentation 文档
2011/09/29 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
复制网页内容,粘贴之后自动加上网址的实现方法(脚本之家特别整理)
2014/10/16 Javascript
JS实现随机乱撞彩色圆球特效的方法
2015/05/05 Javascript
详解javascript中原始数据类型Null和Undefined
2015/12/17 Javascript
浅谈js多维数组和hash数组定义和使用
2016/07/27 Javascript
深入理解JavaScript中Ajax
2016/08/02 Javascript
谈谈target=_new和_blank的不同之处
2016/10/25 Javascript
Angular+Bootstrap+Spring Boot实现分页功能实例代码
2017/07/21 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
2018/08/03 jQuery
vue单页缓存存在的问题及解决方案(小结)
2018/09/25 Javascript
微信小程序简单的canvas裁剪图片功能详解
2019/07/12 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
Javascript表单序列化原理及实现代码详解
2020/10/30 Javascript
js删除指定位置超链接中含有百度与360的标题
2021/01/06 Javascript
如何搜索查找并解决Django相关的问题
2014/06/30 Python
跟老齐学Python之眼花缭乱的运算符
2014/09/14 Python
python3.x上post发送json数据
2018/03/04 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
Python如何在windows环境安装pip及rarfile
2020/06/15 Python
HTML5 script元素async、defer异步加载使用介绍
2013/08/23 HTML / CSS
洲际酒店集团大中华区:IHG中国
2016/08/17 全球购物
德国孕妇装和婴童服装网上商店:bellybutton
2018/04/12 全球购物
美国在线面料商店:Fashion Fabrics Club
2020/01/31 全球购物
英国领先的独立酒精饮料零售商:DrinkSupermarket
2021/01/13 全球购物
私人房屋买卖协议书
2014/10/04 职场文书
2014年财政工作总结
2014/12/10 职场文书
幼儿园卫生保健制度
2015/08/05 职场文书