Golang正则表达式不支持复杂正则和预查问题解决

Golang正则表达式不支持复杂正则和预查问题解决

我有一个需求,需要匹配一段字符串中第几季的这个几,那么按正则表达式的语法,我的表达式应该是这样的

`(?<=第)\d+(?=季)`

然而,当我用go官方包regexp的时候,compile的时候报了个错误:

error parsing regexp: invalid or unsupported Perl syntax: (?<

啥意思呢?

语法错误,不支持(?<,然而我在线运行的时候明明是没错的,这说明go的正则引擎不支持负向预查。

通过查看文档发现同时也是不支持正向预查的,下面这些都是不支持的。

(?=re) before text matching re (NOT SUPPORTED)
(?!re) before text not matching re (NOT SUPPORTED)
(?<=re) after text matching re (NOT SUPPORTED)
(? after text not matching re (NOT SUPPORTED)

但是有些需求用预查确实很方便,比如我想查找“第3部”中的这个3,如果有预查我只需要

(?<=第)[0-9]+(?=部)

这样就可以很简单的查到第和部之间的这个数字,而没有预查的话难道要我先查到第再查部,记录他们的位置去查3吗?

这简直不科学!

我相信前辈们肯定遇到过这个问题而且已经造好轮子了,所以立马去GitHub搜,果然没让我失望,找到了

http://www.github.com/dlclark/regexp2

Regexp2 is a feature-rich RegExp engine for Go. It doesn’t have constant time guarantees like the built-in regexp package, but it allows backtracking and is compatible with Perl5 and .NET. You’ll likely be better off with the RE2 engine from the regexp package and should only use this if you need to write very complex patterns or require compatibility with .NET.

Regexp2是一个功能丰富的正则表达式引擎。 它没有像内置 regexp 包那样的固定时间保证,但是它允许回溯,并与Perl5和. NET 兼容。 如果你需要编写非常复杂的模式,或者需要与. NET. 引擎兼容,那么你最好从 regexp 包中使用RE2引擎,并且应该只使用它。

用法:

用法与 go regexp 包类似。 首先通过 Compile 或者 MustCompile 方法将 正规表达式 转换为状态机。 然后,可以使用返回的regexp结构体查找匹配项。 而且regexp结构是可以安全地跨goroutine使用的。

如何引入:

import “github.com/dlclark/regexp2”
go get -u github.com/dlclark/regexp2

比如:

var res string 
str := "公众号:codeoffer。"
expr:= `(?<=公众号:).*(?=。)`
reg, _ := regexp2.Compile(expr, 0)
m, _ := reg.FindStringMatch(str)
if m != nil {
   res = m.String()
}
fmt.Println(res) 

输出:
codeoffer

这里和regexp的用法有稍微不一样的地方,比如Compile的时候需要传两个参数,第二个RegexOptions表示。。。

默认为0即可,然后匹配后返回的结果是一个group的结构,如果想真正获得结果需要进行一个string(),

组 0嵌入在匹配中。 组 0是一个自动分配的组,它包含整个 Pattern。 这意味着 m.String()m.Group.String()m.Groups()[0].String() 相同。

if m, _ := re.FindStringMatch(`Something to match`); m != nil {
    // the whole match is always group 0
    fmt.Printf("Group 0: %v\n", m.String())
		// you can get all the groups too
		gps := m.Groups()

		// a group can be captured multiple times, so each cap is separately addressable
		fmt.Printf("Group 1, first capture", gps[1].Captures[0].String())
		fmt.Printf("Group 1, second capture", gps[1].Captures[1].String())
	}

比较regexp和regexp2

Category regexp regexp2
Catastrophic backtracking possible no, constant execution time guarantees yes, if your pattern is at risk you can use the re.MatchTimeout field
Python-style capture groups (?Pre) yes no (yes in RE2 compat mode)
.NET-style capture groups (?re) or (?'name're) no yes
comments (?#comment) no yes
branch numbering reset (?|a|b) no no
possessive match (?>re) no yes
positive lookahead (?=re) no yes
negative lookahead (?!re) no yes
positive lookbehind (?<=re) no yes
negative lookbehind (? no yes
back reference \1 no yes
named back reference \k'name' no yes
named ascii character class [[:foo:]] yes no (yes in RE2 compat mode)
conditionals (?(expr)yes|no) no yes

regexp2功能还是很强大的,如果是复杂的正则表达式推荐使用。

你可能感兴趣的:(Coding,Golang,正则表达式,golang,go)