美文网首页
Golang规则表达式之submatch

Golang规则表达式之submatch

作者: CodingCode | 来源:发表于2021-09-14 02:00 被阅读0次

submatch的使用,首先要在规则表达式里面使用grouping’()‘标识出来。

举一个例子:

re := regexp.MustCompile(`a(x*)b`)
fmt.Printf("%q\n", re.FindStringSubmatch("-axxxb-"))
// ["axxxb" "xxx"]
fmt.Printf("%q\n", re.FindStringSubmatch("-axb-"))
["axb" "x"]
fmt.Printf("%q\n", re.FindStringSubmatch("-ab-"))
["axb" "x"]

这里a(x*)b是一个待匹配的规则表达式,其中的(x*)就是submatch。当整个字符串匹配满足规则表达式时,同时就会把对应的submatch也匹配出来。

当然submatch可以有多个,按定义的先后顺序排列。

submatch特别有用的一个地方是提取字符串:

  1. 先判断字符串是否满足给定的规则表达式;
  2. 如果满足,则把其中的一部分提取出来。

在前面的例子中:

  1. 首先判断字符串是否满足字母ab中间包含0个或者多个x的格式。
  2. 如果是,则把其中的所有x提取出来。
  3. 进一步,可以把这些不确定个数的x全部替换成其他字符。

如何放弃submatch

另外,之前我们知道括号也是用来分组用的,例如(ab)+和格式ab+的区分,这个时候虽然用了括号分组,但是有时并不需要这个submatch,只是控制语法的需要。

语法(?:re)就用来放弃这个submatch的功能。

还是举个例子来说更清楚:

re1 := regexp.MustCompile(`a(x*)b(y+)c`)
fmt.Printf("%q\n", re1.FindStringSubmatch("-axxxbyyc-"))
// ["axxxbyyc" "xxx" "yy"]
fmt.Printf("%q\n", re1.FindStringSubmatch("-axbyc-"))
// ["axbyc" "x" "y"]
fmt.Printf("%q\n", re1.FindStringSubmatch("-abc-"))
// []

re2 := regexp.MustCompile(`a(?:x*)b(y+)c`)
fmt.Printf("%q\n", re2.FindStringSubmatch("-axxxbyyc-"))
// ["axxxbyyc" "yy"]
fmt.Printf("%q\n", re2.FindStringSubmatch("-axbyc-"))
// ["axbyc" "y"]
fmt.Printf("%q\n", re2.FindStringSubmatch("-abc-"))
// []

其中group '(x*)'在re1里是一个submatch,而在re2里面不是一个submatch;虽然re1和re2的规则表达式匹配的规则是一样的,但是在结果输出中,这个group并没有被包含再re2的输出中。

如何用命名来约取submatch

还是以前面例子为例:

re := regexp.MustCompile(`a(x*)b(y+)c`)
matches := re.FindStringSubmatch("-axxxbyyc-")

fmt.Printf("%q\n", matches)     // ["axxxbyyc" "xxx" "yy"]
fmt.Printf("%q\n", matches[0])  // "axxxbyyc"
fmt.Printf("%q\n", matches[1])  // "xxx"
fmt.Printf("%q\n", matches[2])  // "yyy"

可以通过matches[index]下标来获取对应的submatch,而golang如果submatch很多的话,而且将来一旦调整修改,下标可能会发生变化,所以golang规则表达式同样支持命名的方式,这样就可以使得代码相对固定。

命名submatch的格式是:(?P<name>re)
同样的例子:

re := regexp.MustCompile(`a(?P<match1>x*)b(?P<match2>y+)c`)
matches := re.FindStringSubmatch("-axxxbyyc-")

match1Index := re.SubexpIndex("match1")
match2Index := re.SubexpIndex("match2")
fmt.Printf("matches[%d]=%q\n", match1Index, matches[match1Index])   // "xxx"
fmt.Printf("matches[%d]=%q\n", match2Index, matches[match2Index])   // "yy"

这样不管以后regular expression pattern 怎么变化,只要名字match1/match2没有发生变化,最终的输出结果都是一致的。

需要注意的是:

  1. index下标从1开始,因为下标0已经分配给了整个匹配串。
  2. 自己要负责保证naming不会重复哈,不然只有第一个有效了(测试结果)。

相关文章

网友评论

      本文标题:Golang规则表达式之submatch

      本文链接:https://www.haomeiwen.com/subject/qcuxgltx.html