3 回答
TA贡献1827条经验 获得超7个赞
遗憾的是,Go中没有外观支持,因此,您可以通过加倍空格(例如与\s)然后与匹配来解决此问题:regexpregexp.MustCompile().ReplaceAllString(d, "$0$0")(?:\s|^)(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)(?:\s|$)
package main
import (
"fmt"
"regexp"
)
func main() {
var d = `foo=bar baz foo:1 foo:234.mds32 notfoo:baz foo:bak foo:nospace foo:bar`
d = regexp.MustCompile(`\s`).ReplaceAllString(d, "$0$0")
r := regexp.MustCompile(`(?:\s|^)(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)(?:\s|$)`)
idx := r.SubexpIndex("primary")
for _, m := range r.FindAllStringSubmatch(d, -1) {
fmt.Printf("%q\n", m[idx])
}
}
请参阅 Go 演示。输出:
"foo=bar baz"
"foo:1"
"foo:234.mds32"
"foo:bak"
"foo:nospace"
"foo:bar"
详细信息:
(?:\s|^)
- 空格或字符串的开头(?P<primary>foo[:=]\S+(?:\s+[^:\s]+)*)
- 组“主要”:冒号或字符,一个或多个非空格,然后零个或多个出现一个或多个空格,然后是一个或多个字符,而不是空格或冒号foo
=
(?:\s|$)
- 白带或字符串的末端。
TA贡献1847条经验 获得超7个赞
您可以采取以下几种方法:
只需将您的模式更改为维克托·斯特里比纽在评论中提到的模式,而不是匹配。这解决了没有恶作剧的问题,但我会列出一些可能适用于类似问题的选择,这些问题不能轻易被否定。
(?:\s|^)(?P<primary>foo[:=]\S+)
.+?
\s
由于问题在于功能不允许重叠,因此不要使用它们!相反,滚动你自己的,用于获取一个匹配项的边界,通过切片字符串来提取匹配的文本,然后执行并循环直到返回零。
FindAll
FindStringSubmatchIndex
d = d[endIndex-1:]
FindStringSubmatchIndex
使用 模式将输入字符串分解为空格分隔的组件,然后丢弃不在 上的组件。您甚至可以改用。其余的将是您想要的匹配项,并且它们周围的空格将被拆分丢弃。在我看来,这个版本比试图使用匹配更清楚地传达了意图。
regexp.Split()
\s+
regexp.Match()
^foo[:=]
strings.HasPrefix("foo:") || strings.HasPrefix("foo=")
TA贡献1799条经验 获得超6个赞
其他人根据要求使用正则表达式给出了很好的答案。我可以大胆地建议一个非正则表达式的答案吗?
我发现正则表达式不是这种情况的最佳解决方案。最好使用拆分字符串以获取子字符串列表。对于每个字符串,根据它是否具有或两者都没有来拆分它。该函数在解析方面做得很好,类似于 中的默认拆分,它跳过了一行中的多个空格。strings.Fields(original)=:Fields()awk
工作示例:https://play.golang.org/p/xXaA9skdplz
original := `foo=bar baz foo:1 foo:234.mds32 notfoo:baz foo:bak foo:nospace foo:bar`
for _, item := range strings.Fields(original) {
if kv := strings.SplitN(item, "=", 2); len(kv) == 2 {
fmt.Printf("key/value: %q -> %q\n", kv[0], kv[1])
} else if kv := strings.SplitN(item, ":", 2); len(kv) == 2 {
fmt.Printf("key/value: %q -> %q\n", kv[0], kv[1])
} else {
fmt.Printf("key: %q\n", item)
}
}
显然,您需要修改此代码以收集答案而不是打印它们。
如果您必须使用正则表达式,请使用其他答案。
- 3 回答
- 0 关注
- 82 浏览
添加回答
举报