匹配直到字符,但是,不要包含该字符

我正在尝试与以下输入进行匹配:

foo=bar baz foo:1  foo:234.mds32  notfoo:baz  foo:bak foo:nospace foo:bar

和输出 6 匹配:除 .匹配项应类似(即不包括尾随空格或前导空格。notfoofoo:bar

一般来说,我试图匹配的规则是:

  • 查找任何 kv 对,其中键为 ,并且 kv 对由 或 分隔。foo=:

  • 对是彼此分离的字符串。kv 对之间可能有多个空格或随机字符串。

  • 作为 ^ 的结果,kv 对必须在两侧具有空格或行开始/结束。

我目前对此最好的正则表达式是 ,然后提取组。'(?:\s|^)(?P<primary>foo[:=].+?)\s'primary

这样做的问题是因为我们包含作为匹配的一部分,我们遇到了重叠正则表达式的问题:因为我们尝试空格字符匹配2x,并且golang正则表达式不返回重叠匹配项。\sfoo:bak foo:nospace foo:bar

在其他正则表达式引擎中,我认为可以使用前瞻,但据我所知,golang正则表达式不允许这样做。

有什么办法可以做到这一点吗?

去游乐场链接: https://play.golang.org/p/n8gnWwpiBSR


千万里不及你
浏览 83回答 3
3回答

慕仙森

遗憾的是,Go中没有外观支持,因此,您可以通过加倍空格(例如与\s)然后与匹配来解决此问题:regexpregexp.MustCompile().ReplaceAllString(d, "$0$0")(?:\s|^)(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)(?:\s|$)package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "regexp")func main() {&nbsp; &nbsp; var d = `foo=bar baz foo:1&nbsp; foo:234.mds32&nbsp; notfoo:baz&nbsp; foo:bak foo:nospace foo:bar`&nbsp; &nbsp; d = regexp.MustCompile(`\s`).ReplaceAllString(d, "$0$0")&nbsp; &nbsp; r := regexp.MustCompile(`(?:\s|^)(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)(?:\s|$)`)&nbsp; &nbsp; idx := r.SubexpIndex("primary")&nbsp; &nbsp; for _, m := range r.FindAllStringSubmatch(d, -1) {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("%q\n", m[idx])&nbsp; &nbsp; }}请参阅 Go 演示。输出:"foo=bar&nbsp; baz""foo:1""foo:234.mds32""foo:bak""foo:nospace""foo:bar"详细信息:(?:\s|^)- 空格或字符串的开头(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)- 组“主要”:冒号或字符,一个或多个非空格,然后零个或多个出现一个或多个空格,然后是一个或多个字符,而不是空格或冒号foo=(?:\s|$)- 白带或字符串的末端。

aluckdog

您可以采取以下几种方法:只需将您的模式更改为维克托·斯特里比纽在评论中提到的模式,而不是匹配。这解决了没有恶作剧的问题,但我会列出一些可能适用于类似问题的选择,这些问题不能轻易被否定。(?:\s|^)(?P<primary>foo[:=]\S+).+?\s由于问题在于功能不允许重叠,因此不要使用它们!相反,滚动你自己的,用于获取一个匹配项的边界,通过切片字符串来提取匹配的文本,然后执行并循环直到返回零。FindAllFindStringSubmatchIndexd = d[endIndex-1:]FindStringSubmatchIndex使用 模式将输入字符串分解为空格分隔的组件,然后丢弃不在 上的组件。您甚至可以改用。其余的将是您想要的匹配项,并且它们周围的空格将被拆分丢弃。在我看来,这个版本比试图使用匹配更清楚地传达了意图。regexp.Split()\s+regexp.Match()^foo[:=]strings.HasPrefix("foo:") || strings.HasPrefix("foo=")

哈士奇WWW

其他人根据要求使用正则表达式给出了很好的答案。我可以大胆地建议一个非正则表达式的答案吗?我发现正则表达式不是这种情况的最佳解决方案。最好使用拆分字符串以获取子字符串列表。对于每个字符串,根据它是否具有或两者都没有来拆分它。该函数在解析方面做得很好,类似于 中的默认拆分,它跳过了一行中的多个空格。strings.Fields(original)=:Fields()awk工作示例:https://play.golang.org/p/xXaA9skdplz&nbsp; &nbsp; original := `foo=bar baz foo:1&nbsp; foo:234.mds32&nbsp; notfoo:baz&nbsp; foo:bak foo:nospace foo:bar`&nbsp; &nbsp; for _, item := range strings.Fields(original) {&nbsp; &nbsp; &nbsp; &nbsp; if kv := strings.SplitN(item, "=", 2); len(kv) == 2 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("key/value: %q -> %q\n", kv[0], kv[1])&nbsp; &nbsp; &nbsp; &nbsp; } else if kv := strings.SplitN(item, ":", 2); len(kv) == 2 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("key/value: %q -> %q\n", kv[0], kv[1])&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("key: %q\n", item)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }显然,您需要修改此代码以收集答案而不是打印它们。如果您必须使用正则表达式,请使用其他答案。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go