正则中有分组这个功能,在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)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    输出为:

    [Alice 20 alice@gmail.com Alice 20 alice@gmail.com], [ name age email], 4, 4
    {
    “age”: “20”,
    “email”: “alice@gmail.com”,
    “name”: “Alice”
    }
    1
    2
    3
    4
    5
    6
    注意 [ name age email]有4个元素, 第一个为””。

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

    Alice 20 alice@gmail.com
    Bob 25 bob@outlook.com
    gerrylon 26 gerrylon@github.com

    更多内容
    1
    2
    3
    4
    5
    和上面一样, 不过这次转出来是一个slice of map, 也就是多个map。
    代码如下:

    // 文件内容直接用字符串表示
    usersStr := <br /> Alice 20 alice@gmail.com<br /> Bob 25 bob@outlook.com<br /> gerrylon 26 gerrylon@github.com<br />

    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)

    1. // 对每一行生成一个map<br /> for j, name := range groupNames {<br /> if j != 0 && name != "" {<br /> m[name] = strings.TrimSpace(user[j])<br /> }<br /> }<br /> result = append(result, m)<br />}

    prettyResult, _ := json.MarshalIndent(result, “”, “ “)
    fmt.Println(string(prettyResult))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    输出为:

    [
    {
    “age”: “20”,
    “email”: “alice@gmail.com”,
    “name”: “Alice”
    },
    {
    “age”: “25”,
    “email”: “bob@outlook.com”,
    “name”: “Bob”
    },
    {
    “age”: “26”,
    “email”: “gerrylon@github.com”,
    “name”: “gerrylon”
    }
    ]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    总结
    使用命名分组可以使正则表示的意义更清晰。
    转换为map更加符合人类的阅读习惯,不过比一般的根据索引取分组值麻烦一些。
    参考:
    https://stackoverflow.com/questions/20750843/using-named-matches-from-go-regex

    欢迎补充指正!
    ————————————————
    版权声明:本文为CSDN博主「butterfly5211314」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/butterfly5211314/article/details/82532970