我发现许多类似的问题不适用于Go regex 语法。
我试图匹配的字符串是anything/anything/somestring. 使用模式\/.*\/.*\/(.*),我将匹配somestring,但我试图匹配除包含somestring.
大多数答案都建议使用类似\/.*\/.*\/((?!somestring).*),但是在 golang regexp 中我得到:? The preceding token is not quantifiable。
澄清/test/test/MATCH一下:会产生匹配,而/test/test/somestring不会。这可能与(有限的)Go regex 语法有关吗?
更新
Goregexp模块不支持lookaheads,因为这个包保证在O(n) 时间内运行,并且作者没有找到一种在不违反这些约束的情况下引入lookarounds 的方法。
但是,您可以使用不同的解决方法。对于当前的模式,您可以使用http://www.formauri.es/personal/pgimeno/misc/non-match-regex Web 服务来生成 POSIX 兼容的否定模式。例如somestring,它会生成一个^([^s]|s(s|o(s|m(s|es(omes)*(s|t(s|r(s|i(s|ns)))|o(s|ms)))))*([^os]|o([^ms]|m([^es]|e([^s]|s(omes)*([^ost]|t([^rs]|r([^is]|i([^ns]|n[^gs])))|o([^ms]|m([^es]|e[^s]))))))))*(s(s|o(s|m(s|es(omes)*(s|t(s|r(s|i(s|ns)))|o(s|ms)))))*(o((me?)?|mes(omes)*(t(r?|rin?)|o(me?)?)?))?)?$正则表达式,为了在原始正则表达式中使用它,您只需将最后一个替换为(.*),(<part after ^>)即正则表达式将如下所示
/[^/]*/[^/]*/(([^s]|s(s|o(s|m(s|es(omes)*(s|t(s|r(s|i(s|ns)))|o(s|ms)))))*([^os]|o([^ms]|m([^es]|e([^s]|s(omes)*([^ost]|t([^rs]|r([^is]|i([^ns]|n[^gs])))|o([^ms]|m([^es]|e[^s]))))))))*(s(s|o(s|m(s|es(omes)*(s|t(s|r(s|i(s|ns)))|o(s|ms)))))*(o((me?)?|mes(omes)*(t(r?|rin?)|o(me?)?)?))?)?)$
Run Code Online (Sandbox Code Playgroud)
请参阅正则表达式演示。
为了确保正则表达式仅捕获第三个反斜杠之后的部分,前两个.*模式将替换为[^/]*匹配除 之外的零个或多个字符/。(在演示中,我\n还添加了 ,以避免单个多行字符串演示中的跨行匹配)。
最初接受的答案
不应anything/anything/somestring表示为\/.*\/.*\/(.*)。第一个.*匹配到最后一个,但/字符串中只有一个。您需要使用否定字符类[^/](不是/Go 正则表达式中不应转义的字符类)。
由于 Go 使用的 RE2 不支持前瞻,因此您需要捕获(正如JimB 在评论中提到的那样)您感兴趣的所有三个部分,并在检查捕获组 #1 值后,决定返回什么:
包主
import (
"fmt"
"regexp"
)
func main() {
s := "anything/anything/somestring"
r := regexp.MustCompile(`^[^/]+/[^/]+/(.*)`)
val := r.FindStringSubmatch(s)
// fmt.Println(val[1]) // -> somestring
if len(val) > 1 && val[1] != "somestring" { // val has more than 1 element and is not equal to somestring?
fmt.Println(val[1]) // Use val[1]
} else {
fmt.Println("No match") // Else, report no match
}
}
Run Code Online (Sandbox Code Playgroud)
查看Go 演示
根据 Russ Cox 的说法, Golang 有意忽略了此功能,因为无法在 O(n) 时间内实现它以满足真正正则表达式的约束:
缺少通用断言,就像缺少反向引用一样,并不是我们对正则表达式风格的声明。这是不知道如何有效实施它们的结果。如果您可以在保留当前包 regexp 做出的保证的同时实现它们,即它对输入进行单次扫描并在 O(n) 时间内运行,那么我很乐意审查和批准该 CL。然而,这五年我一直在思考如何做到这一点,断断续续,一无所获。
看起来最好的方法是在上面 JimB 提到的之后手动检查匹配。