在Go语言中用正则表达式将括号内数据拆分至命名分组
Go语言正则实现版本约束的命名分组提取
针对你提到的两种版本约束格式,Go语言的正则虽然不支持前后瞻,但可以通过两种方式实现需求:
方案1:单正则直接捕获(适配1-2个约束)
直接编写一个能匹配两种格式的正则,通过命名分组一次性提取所有需要的字段:
^(?P<n>\S+) \((?P<o1>[>=<~]+) (?P<v1>\S+)(?:, (?P<o2>[>=<~]+) (?P<v2>\S+))?\)$
匹配逻辑:
(?P<n>\S+):捕获括号外的非空白字符(即示例中的a或b)(?P<o1>[>=<~]+):捕获第一个运算符(?P<v1>\S+):捕获第一个版本号(?:, (?P<o2>[>=<~]+) (?P<v2>\S+))?:可选的第二个约束组,仅当存在逗号分隔的第二个约束时才匹配
代码示例:
package main import ( "fmt" "regexp" ) func main() { inputLines := []string{ "a (>= 1.1)", "b (>= 1.1, < 2.0)", } reg := regexp.MustCompile(`^(?P<n>\S+) \((?P<o1>[>=<~]+) (?P<v1>\S+)(?:, (?P<o2>[>=<~]+) (?P<v2>\S+))?\)$`) for _, line := range inputLines { submatches := reg.FindStringSubmatch(line) if submatches == nil { fmt.Printf("无法匹配行:%s\n", line) continue } fmt.Printf("n -> %s\n", submatches[reg.SubexpIndex("n")]) fmt.Printf("o1 -> %s\n", submatches[reg.SubexpIndex("o1")]) fmt.Printf("v1 -> %s\n", submatches[reg.SubexpIndex("v1")]) o2Idx := reg.SubexpIndex("o2") if o2Idx != -1 && submatches[o2Idx] != "" { fmt.Printf("o2 -> %s\n", submatches[o2Idx]) fmt.Printf("v2 -> %s\n", submatches[reg.SubexpIndex("v2")]) } fmt.Println("---") } }
方案2:两步处理(支持任意数量约束)
如果需要支持3个及以上的版本约束,建议先捕获名称和整体约束内容,再拆分单个约束:
- 第一步正则捕获名称和括号内的所有约束:
^(?P<n>\S+) \((?P<constraints>(?:[>=<~]+ \S+(?:, )?)+)\)$
- 第二步用简单正则
([>=<~]+) (\S+)循环匹配constraints内容,提取每一组运算符和版本号。
代码示例:
package main import ( "fmt" "regexp" ) func main() { inputLines := []string{ "a (>= 1.1)", "b (>= 1.1, < 2.0)", "c (> 0.5, <= 1.0, != 0.8)", } regMain := regexp.MustCompile(`^(?P<n>\S+) \((?P<constraints>(?:[>=<~]+ \S+(?:, )?)+)\)$`) regConstraint := regexp.MustCompile(`([>=<~]+) (\S+)`) for _, line := range inputLines { mainMatch := regMain.FindStringSubmatch(line) if mainMatch == nil { fmt.Printf("无法匹配行:%s\n", line) continue } name := mainMatch[regMain.SubexpIndex("n")] constraints := mainMatch[regMain.SubexpIndex("constraints")] fmt.Printf("n -> %s\n", name) matches := regConstraint.FindAllStringSubmatch(constraints, -1) for i, match := range matches { fmt.Printf("o%d -> %s\n", i+1, match[1]) fmt.Printf("v%d -> %s\n", i+1, match[2]) } fmt.Println("---") } }
内容的提问来源于stack exchange,提问作者Tomer S
相关产品推荐
相关产品推荐

