golang正则之命名分组

版权声明:转载请注明出处,谢谢。 https://blog.csdn.net/butterfly5211314/article/details/82532970

正则中有分组这个功能,在golang中也可以使用命名分组。

一次匹配的情况

场景还原如下:

有一行文本,格式为:姓名 年龄 邮箱地址
请将其转换为一个map

代码实现如下:

str := `Alice 20 [email protected]`

// 使用命名分组,显得更清晰
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 [email protected] Alice 20 [email protected]], [ name age email], 4, 4
{
  "age": "20",
  "email": "[email protected]",
  "name": "Alice"
}

注意 [ name age email]有4个元素, 第一个为""

多次匹配的情况

接上面的例子,实现一个更贴近现实的需求:
有一个文件, 内容大致如下:

Alice 20 [email protected]
Bob 25 [email protected]
gerrylon 26 [email protected]
...
更多内容

和上面一样, 不过这次转出来是一个slice of map, 也就是多个map。
代码如下:

// 文件内容直接用字符串表示
usersStr := `
    Alice 20 [email protected]
    Bob 25 [email protected]
    gerrylon 26 [email protected]
`

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": "[email protected]",
    "name": "Alice"
  },
  {
    "age": "25",
    "email": "[email protected]",
    "name": "Bob"
  },
  {
    "age": "26",
    "email": "[email protected]",
    "name": "gerrylon"
  }
]

总结

  • 使用命名分组可以使正则表示的意义更清晰。
  • 转换为map更加符合人类的阅读习惯,不过比一般的根据索引取分组值麻烦一些。

参考:
https://stackoverflow.com/questions/20750843/using-named-matches-from-go-regex


欢迎补充指正!

猜你喜欢

转载自blog.csdn.net/butterfly5211314/article/details/82532970