Pla*_*fan 41 regex go capture-group
我正在将一个库从Ruby移植到Go,并且刚刚发现Ruby中的正则表达式与Go(谷歌RE2)不兼容.我注意到Ruby和Java(以及其他语言使用PCRE正则表达式(perl兼容,它支持捕获组)),因此我需要重新编写表达式,以便它们在Go中编译好.
例如,我有以下正则表达式:
`(?<Year>\d{4})-(?<Month>\d{2})-(?<Day>\d{2})`
Run Code Online (Sandbox Code Playgroud)
这应该接受如下输入:
2001-01-20
Run Code Online (Sandbox Code Playgroud)
捕获组允许将年,月和日捕获到变量中.为了获得每个组的价值,这很容易; 您只需使用组名索引返回的匹配数据,然后返回值.所以,例如获得年份,像这样的伪代码:
m=expression.Match("2001-01-20")
year = m["Year"]
Run Code Online (Sandbox Code Playgroud)
这是我在表达式中使用很多的模式,所以我需要做很多重写.
那么,有没有办法在Go regexp中获得这种功能; 我该如何重写这些表达式?
thw*_*hwd 58
我该如何重写这些表达式?
添加一些诗篇,如定义在这里:
(?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2})
Run Code Online (Sandbox Code Playgroud)
交叉引用捕获组名称re.SubexpNames()
.
使用方法如下:
package main
import (
"fmt"
"regexp"
)
func main() {
r := regexp.MustCompile(`(?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2})`)
fmt.Printf("%#v\n", r.FindStringSubmatch(`2015-05-27`))
fmt.Printf("%#v\n", r.SubexpNames())
}
Run Code Online (Sandbox Code Playgroud)
elu*_*eci 21
我创建了一个处理url表达式的函数,但它也适合你的需求.您可以检查此代码段,但它的工作原理如下:
/**
* Parses url with the given regular expression and returns the
* group values defined in the expression.
*
*/
func getParams(regEx, url string) (paramsMap map[string]string) {
var compRegEx = regexp.MustCompile(regEx)
match := compRegEx.FindStringSubmatch(url)
paramsMap = make(map[string]string)
for i, name := range compRegEx.SubexpNames() {
if i > 0 && i <= len(match) {
paramsMap[name] = match[i]
}
}
return
}
Run Code Online (Sandbox Code Playgroud)
您可以使用此功能,如:
params := getParams(`(?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2})`, `2015-05-27`)
fmt.Println(params)
Run Code Online (Sandbox Code Playgroud)
输出将是:
map[Year:2015 Month:05 Day:27]
Run Code Online (Sandbox Code Playgroud)
Vas*_*leM 11
要在不调用循环内部的匿名函数的情况下提高RAM和CPU使用率,而不使用"append"函数复制内部循环内的数组,请参阅下一个示例:
您可以使用多行文本存储多个子组,而不使用'+'附加字符串,也不使用for循环for for循环(就像此处发布的其他示例一样).
txt := `2001-01-20
2009-03-22
2018-02-25
2018-06-07`
regex := *regexp.MustCompile(`(?s)(\d{4})-(\d{2})-(\d{2})`)
res := regex.FindAllStringSubmatch(txt, -1)
for i := range res {
//like Java: match.group(1), match.gropu(2), etc
fmt.Printf("year: %s, month: %s, day: %s\n", res[i][1], res[i][2], res[i][3])
}
Run Code Online (Sandbox Code Playgroud)
输出:
year: 2001, month: 01, day: 20
year: 2009, month: 03, day: 22
year: 2018, month: 02, day: 25
year: 2018, month: 06, day: 07
Run Code Online (Sandbox Code Playgroud)
注意:res [i] [0] = ~match.group(0)Java
如果要存储此信息,请使用结构类型:
type date struct {
y,m,d int
}
...
func main() {
...
dates := make([]date, 0, len(res))
for ... {
dates[index] = date{y: res[index][1], m: res[index][2], d: res[index][3]}
}
}
Run Code Online (Sandbox Code Playgroud)
最好使用匿名组(性能改进)
使用Github上发布的"ReplaceAllGroupFunc"是个坏主意,因为:
根据@VasileM 答案确定组名的简单方法。
免责声明:这与内存/CPU/时间优化无关
package main
import (
"fmt"
"regexp"
)
func main() {
r := regexp.MustCompile(`^(?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2})$`)
res := r.FindStringSubmatch(`2015-05-27`)
names := r.SubexpNames()
for i, _ := range res {
if i != 0 {
fmt.Println(names[i], res[i])
}
}
}
Run Code Online (Sandbox Code Playgroud)
https://play.golang.org/p/Y9cIVhMa2pU
从 GO 1.15 开始,您可以使用Regexp.SubexpIndex
. 您可以在https://golang.org/doc/go1.15#regexp查看发行说明。
根据您的示例,您将有以下内容:
re := regexp.MustCompile(`(?P<Year>\d{4})-(?P<Month>\d{2})-(?P<Day>\d{2})`)
matches := re.FindStringSubmatch("Some random date: 2001-01-20")
yearIndex := re.SubexpIndex("Year")
fmt.Println(matches[yearIndex])
Run Code Online (Sandbox Code Playgroud)
您可以在https://play.golang.org/p/ImJ7i_ZQ3Hu检查并执行此示例。