有没有办法使用 Go.Regexp 匹配除常量字符串之外的所有内容?

Rya*_*yan 6 regex go

我发现许多类似的问题不适用于Go regex 语法

我试图匹配的字符串是anything/anything/somestring. 使用模式\/.*\/.*\/(.*),我将匹配somestring,但我试图匹配除包含somestring.

大多数答案都建议使用类似\/.*\/.*\/((?!somestring).*),但是在 golang regexp 中我得到:? The preceding token is not quantifiable

澄清/test/test/MATCH一下:会产生匹配,而/test/test/somestring不会。这可能与(有限的)Go regex 语法有关吗?

Wik*_*żew 9

更新

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 演示


Rya*_*yan 6

根据 Russ Cox 的说法, Golang 有意忽略了此功能,因为无法在 O(n) 时间内实现它以满足真正正则表达式的约束:

缺少通用断言,就像缺少反向引用一样,并不是我们对正则表达式风格的声明。这是不知道如何有效实施它们的结果。如果您可以在保留当前包 regexp 做出的保证的同时实现它们,即它对输入进行单次扫描并在 O(n) 时间内运行,那么我很乐意审查和批准该 CL。然而,这五年我一直在思考如何做到这一点,断断续续,一无所获。

看起来最好的方法是在上面 JimB 提到的之后手动检查匹配。