Golang正则表达式使用及简单示例
我发现很多从写脚本转过来写Go代码的开发者都会对Go的正则表达式 (Regular Expression) 功能有微词。普遍觉得其灵活性和完善度都不太给力。其实两个都是有原因的。灵活性其实主要是对Go regexp包的设计哲学不理解。完善度则主要是因为regexp包承诺match的时间与输入长度成线性关系,因此有些表达式就无法支持了, 比如 (?!re)
:
The regexp implementation provided by this package is guaranteed to run in time linear in the size of the input.
所以,本质上这不是一个「够不够完善」的问题,而是「技术实现决定了它支持程度就是这样」。更多讨论可以关注这里。
Go的正则表达式采用RE2语法,详细语法及支持情况可以参阅[这里]。
regex包的设计原则
regexp包的方法命名规则如下:
Find(All)?(String)?(Submatch)?(Index)?
- 包含All的方法捕获所有match, 返回值是一个slice. 同时一般会提供一个参数n作为最大匹配次数。
- 包含String的方法对string类型进行匹配,反之对[]byte进行匹配。
- 包含Submatch的方法返回所有子匹配,返回值是一个slice. 位置0是对应整个正则表达式匹配结果,位置n(n>0)是第n个子表达式(group) 匹配结果。
- 包含Index的方法返回匹配的位置。例如,返回loc []int, 则与之对应的匹配字符为src[loc[0]:loc[1]].
匹配Unicode字符
Unicode character class (one-letter name): \pN
Unicode character class: \p{Greek}
1 2 3 4 5 6 |
test1 := “123中文汉字abc321” reg1 := regexp.MustCompile(`\p{L}+`) match := reg1.FindString(test1) log.Println(match) // 输出: 中文汉字abc |
含参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
test1 := `123中文汉字abc321` reg2 := regexp.MustCompile(`(?P<All>(?P<Number>\d+)(?P<Letter>\p{L}+)(?P<Number>\d+))`) names := reg2.SubexpNames() for k, v := range names { log.Printf("%d: %s", k, v) } matches := reg2.FindStringSubmatch(test1) for k, v := range matches { log.Printf("%d: %s", k, v) } // 输出: // 2016/04/25 16:26:18 0: // 2016/04/25 16:26:18 1: All // 2016/04/25 16:26:18 2: Number // 2016/04/25 16:26:18 3: Letter // 2016/04/25 16:26:18 4: Number // 2016/04/25 16:26:18 0: 123中文汉字abc321 // 2016/04/25 16:26:18 1: 123中文汉字abc321 // 2016/04/25 16:26:18 2: 123 // 2016/04/25 16:26:18 3: 中文汉字abc // 2016/04/25 16:26:18 4: 321 |