匹配在golang中始终用逗号或空格分隔的重复模式

时间:2019-06-25 07:40:39

标签: regex go

我正在尝试在一个字符串文字中解析多个标签。 例如name=testName, key=testKey, columns=(c1, c2, c3),我可能会考虑在不久的将来在此字符串中添加更多具有不同语法的标签。 因此,研究正则表达式以实现它是很自然的。

至于语法: 有效:

`name=testName,key=testKey`
`name=testName, key=testKey`
`name=testName key=testKey`
`name=testName    key=testKey`
`name=testName key=testKey columns=(c1 c2 c3)`
`name=testName key=testKey columns=(c1, c2, c3)`
`name=testName, key=testKey, columns=(c1 c2 c3)`

无效:

`name=testName,, key=testKey`  (multiple commas in between)
`name=testName, key=testKey,`  (end with a comma)
`name=testName, key=testKey, columns=(c1,c2 c3)` u can only use comma or whitespace consistently inside columns, the rule applies to the whole tags as well. see below
`name=testName, key=testKey columns=(c1,c2,c3)`

我提出了整个模式,如下所示:

((name=\w+|key=\w+)+,\s*)*(name=\w+|key=\w+)+

我想知道是否可以将子模式设置为正则表达式,然后将它们组合成更大的模式。 例如

patternName :=  regexp.MustCompile(`name=\w+`)
patternKey := regexp.MustCompile(`key=\w+`)
pattern = ((patternName|patternKey)+,\s*)*(patternName|patternKey)+

考虑到我将添加更多标签,整个模式肯定会变得更大且更难看。有没有类似组合方式的优雅方式?

1 个答案:

答案 0 :(得分:1)

是的,您想要的是可能的。 regexp.Regexp类型具有String()方法,该方法产生字符串表示形式。因此,您可以使用它来组合正则表达式:

patternName :=  regexp.MustCompile(`name=\w+`)
patternKey := regexp.MustCompile(`key=\w+`)
pattern = regexp.MustCompile(`((`+patternName.String()+`|`+patternKey.String()+`)+,\s*)*(`+patternName.String()+`|`+patternKey.String()`+`)+`)

可以使用fmt.Sprintf缩短(尽管效率较低):

pattern = regexp.MustCompile(fmt.Sprintf(`((%s|%s)+,\s*)*(%s|%s)+`, patternName, patternKey, patternName, patternKey)

但是仅仅因为有可能并不意味着您应该这样做...

使用标准的文本解析方法(例如strings.Splitstrings.FieldsFunc等),可以更轻松地处理您的特定示例。鉴于您提供的示例输入,我将以这种方式进行:

  1. 以空格/逗号分隔
  2. 将每个结果均等分。
  3. 验证密钥名称是否正确(name和/或key

与正则表达式相比,此代码更容易阅读,并且执行速度可能快数百或数千倍。这种方法还很容易实现流处理,如果您要处理数百个或更多记录,并且不想消耗大量内存,这将是一个很大的好处。 (也可以使用Regexp来做到这一点,但是可读性仍然较低。)