为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中模拟负向后视

如何在 Go 中模拟负向后视

Go
慕村9548890 2021-11-22 10:42:50
我正在尝试编写一个可以提取命令的正则表达式,这是到目前为止我使用否定的lookbehind断言所得到的:\b(?<![@#\/])\w.*所以输入:/msg @nickname #channel foo bar baz/foo #channel @nickname foo bar baz foo bar bazfoo bar baz每次都被提取。请参阅工作示例 https://regex101.com/r/lF9aG7/3然而,在 Go 中这不会编译http://play.golang.org/p/gkkVZgScS_它抛出:panic: regexp: Compile(`\b(?<![@#\/])\w.*`): error parsing regexp: invalid or unsupported Perl syntax: `(?<`我做了一些研究并意识到语言中不支持负向后视来保证 O(n) 时间。我怎样才能重写这个正则表达式,让它在没有负面回顾的情况下做同样的事情?
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

由于在否定的回顾中,您只使用了一个简单的字符集;您可以用否定字符集替换它:


\b[^@#/]\w.*

如果在字符串的开头允许,则使用^锚点:


(?:^|[^@#\/])\b\w.*

根据您问题中 Go 游乐场链接中的示例,我认为您希望过滤掉所有以[#@/]. 您可以使用一个filter函数:


func Filter(vs []string, f func(string) bool) []string {

    vsf := make([]string, 0)

    for _, v := range vs {

        if f(v) {

            vsf = append(vsf, v)

        }

    }

    return vsf

}

和一个Process函数,它利用了上面的过滤器:


func Process(inp string) string {

    t := strings.Split(inp, " ")

    t = Filter(t, func(x string) bool {

        return strings.Index(x, "#") != 0 &&

            strings.Index(x, "@") != 0 &&

            strings.Index(x, "/") != 0

    })

    return strings.Join(t, " ")

}

它可以在操场上看到http://play.golang.org/p/ntJRNxJTxo


查看完整回答
反对 回复 2021-11-22
?
慕的地10843

TA贡献1785条经验 获得超8个赞

您实际上可以匹配前面的字符(或行的开头)并使用组在子表达式中获取所需的文本。

正则表达式

(?:^|[^@#/])\b(\w+)
  • (?:^|[^@#/])匹配^行首或[^@#/]任何字符,除了@#/

  • \b 断言单词开头的单词边界

  • (\w+) 生成子表达式

    • 并匹配\w+任意数量的单词字符

代码

cmds := []string{

    `/msg @nickname #channel foo bar baz`,

    `#channel @nickname foo bar baz /foo`,

    `foo bar baz @nickname #channel`,

    `foo bar baz#channel`}


regex := regexp.MustCompile(`(?:^|[^@#/])\b(\w+)`)



// Loop all cmds

for _, cmd := range cmds{

    // Find all matches and subexpressions

    matches := regex.FindAllStringSubmatch(cmd, -1)


    fmt.Printf("`%v` \t==>\n", cmd)


    // Loop all matches

    for n, match := range matches {

        // match[1] holds the text matched by the first subexpression (1st set of parentheses)

        fmt.Printf("\t%v. `%v`\n", n, match[1])

    }

}

输出


`/msg @nickname #channel foo bar baz`   ==>

    0. `foo`

    1. `bar`

    2. `baz`

`#channel @nickname foo bar baz /foo`   ==>

    0. `foo`

    1. `bar`

    2. `baz`

`foo bar baz @nickname #channel`    ==>

    0. `foo`

    1. `bar`

    2. `baz`

`foo bar baz#channel`   ==>

    0. `foo`

    1. `bar`

    2. `baz`

游乐场

http://play.golang.org/p/AaX9Cg-7Vx


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信