Golang下匹配无嵌套括号外&&的无负向预查正则方案
需求说明
给定表达式:
{field1} == value1 && {field2} == value2 && ({field3} == value3 && {field4} == value4) && {field5} == value5
需要匹配所有括号外的&&(忽略括号内value3与field4之间的&&),最终按这些括号外的&&分割,得到两个结果:
- 匹配到的
&&列表:[&&, &&, &&] - 分割后的表达式片段列表:
[{field1} == value1, {field2} == value2, ({field3} == value3 && {field4} == value4), {field5} == value5]
原正则(\&\&)(?![^\(]*\))可实现需求,但Golang不支持负向预查,以下是无负向预查的实现方案:
方案一:手动遍历字符串(推荐)
通过遍历字符串跟踪括号嵌套深度,当深度为0时遇到的&&即为目标匹配项,同时记录分割点。该方案逻辑清晰,支持多层嵌套括号,不受正则特性限制。
示例代码:
package main import ( "fmt" "strings" ) func splitOutsideParens(s string) ([]string, []string) { var ands []string var parts []string var current strings.Builder depth := 0 for i := 0; i < len(s); i++ { switch s[i] { case '(': depth++ current.WriteByte(s[i]) case ')': depth-- current.WriteByte(s[i]) case '&': // 检查是否为&&且当前处于括号外(深度为0) if i+1 < len(s) && s[i+1] == '&' && depth == 0 { parts = append(parts, strings.TrimSpace(current.String())) current.Reset() ands = append(ands, "&&") i++ // 跳过下一个& } else { current.WriteByte(s[i]) } default: current.WriteByte(s[i]) } } // 添加最后一段内容 if current.Len() > 0 { parts = append(parts, strings.TrimSpace(current.String())) } return ands, parts } func main() { input := "{field1} == value1 && {field2} == value2 && ({field3} == value3 && {field4} == value4) && {field5} == value5" ands, parts := splitOutsideParens(input) fmt.Printf("[%s]\n", strings.Join(ands, ", ")) fmt.Printf("[%s]\n", strings.Join(parts, ", ")) }
运行结果:
[&&, &&, &&] [{field1} == value1, {field2} == value2, ({field3} == value3 && {field4} == value4), {field5} == value5]
方案二:Golang正则模拟(仅适用于单层括号场景)
利用正则捕获组区分括号内内容与括号外的&&,但该方案仅支持单层括号,多层嵌套时会失效。
示例代码:
package main import ( "fmt" "regexp" "strings" ) func main() { input := "{field1} == value1 && {field2} == value2 && ({field3} == value3 && {field4} == value4) && {field5} == value5" re := regexp.MustCompile(`(\([^()]*\))|(&&)`) var ands []string var parts []string var temp strings.Builder matches := re.FindAllStringSubmatchIndex(input, -1) prev := 0 for _, match := range matches { // 写入当前匹配前的内容 temp.WriteString(input[prev:match[0]]) prev = match[1] if match[2] != -1 { // 匹配到括号内容,直接写入 temp.WriteString(input[match[2]:match[3]]) } else if match[4] != -1 { // 匹配到括号外的&&,记录片段和&& parts = append(parts, strings.TrimSpace(temp.String())) temp.Reset() ands = append(ands, "&&") } } // 添加最后一段内容 if prev < len(input) { temp.WriteString(input[prev:]) parts = append(parts, strings.TrimSpace(temp.String())) } fmt.Printf("[%s]\n", strings.Join(ands, ", ")) fmt.Printf("[%s]\n", strings.Join(parts, ", ")) }
内容的提问来源于stack exchange,提问作者Tsay
相关产品推荐
相关产品推荐

