Go语言实现带嵌套标记的字符串提取及重复标记处理
Go语言处理嵌套MARKER标记的提取方案
原有的单实例提取代码只能处理无嵌套的场景,要支持嵌套结构并把结果按MARKERNAME归类,我们需要通过跟踪标记嵌套深度来实现,同时用map存储结果(因为MARKERNAME可能重复,所以map的值用切片类型来存多个匹配内容)。
核心思路
- 遍历目标字符串,定位所有
MARKER开头的起始标记,提取对应的MARKERNAME - 维护一个深度计数器:每遇到一个
MARKER XXX就+1,每遇到ENDMARKER就-1 - 当深度从1降到0时,说明找到了当前MARKER对应的结束位置,截取中间的内容
- 把截取的内容按MARKERNAME存入map,重复的NAME会追加到对应切片中
完整实现代码
package main import ( "strings" ) // ParseMarkers 提取所有带嵌套的MARKER内容,返回map[MARKERNAME][]内容 func ParseMarkers(input string) map[string][]string { result := make(map[string][]string) inputLen := len(input) startMarkerPrefix := "MARKER " endMarker := "ENDMARKER" endMarkerLen := len(endMarker) i := 0 for i < inputLen { // 查找下一个MARKER起始位置 startIdx := strings.Index(input[i:], startMarkerPrefix) if startIdx == -1 { break } startIdx += i // 转换为全局索引 nameStart := startIdx + len(startMarkerPrefix) // 提取MARKERNAME:默认NAME是连续非空白字符,可根据需求调整规则 nameEnd := nameStart for nameEnd < inputLen && !strings.ContainsAny(string(input[nameEnd]), " \n\r\t") { nameEnd++ } markerName := input[nameStart:nameEnd] // 定位到MARKERNAME结束后的位置,开始找对应的ENDMARKER currentPos := nameEnd depth := 1 for currentPos < inputLen && depth > 0 { // 查找下一个ENDMARKER或MARKER endIdx := strings.Index(input[currentPos:], endMarker) nextMarkerIdx := strings.Index(input[currentPos:], startMarkerPrefix) // 优先处理更近的标记 if endIdx == -1 { // 未找到匹配的ENDMARKER,视为无效片段,跳出循环 break } if nextMarkerIdx != -1 && nextMarkerIdx < endIdx { // 遇到嵌套的MARKER,深度+1 depth++ currentPos += nextMarkerIdx + len(startMarkerPrefix) } else { // 遇到ENDMARKER,深度-1 depth-- if depth == 0 { // 找到当前MARKER对应的结束位置,截取内容 content := input[nameEnd:currentPos] // 可选:去除内容前后空白,按需调整 content = strings.TrimSpace(content) result[markerName] = append(result[markerName], content) } currentPos += endIdx + endMarkerLen } } i = currentPos } return result } // GetMarkerContent 根据MARKERNAME从解析结果中获取对应内容 func GetMarkerContent(parsed map[string][]string, name string) ([]string, bool) { content, ok := parsed[name] return content, ok } // 使用示例 func main() { input := ` MARKER BOB 这是BOB的第一层内容 MARKER JUNE JUNE的嵌套内容块 MARKER BOB 嵌套的BOB子内容 ENDMARKER ENDMARKER MARKER TED TED的独立内容 ENDMARKER ENDMARKER ` parsed := ParseMarkers(input) // 获取BOB的所有内容 bobContent, _ := GetMarkerContent(parsed, "BOB") println("BOB的内容:") for _, c := range bobContent { println("-", c) } // 获取JUNE的内容 juneContent, _ := GetMarkerContent(parsed, "JUNE") println("\nJUNE的内容:") for _, c := range juneContent { println("-", c) } }
代码说明
- MARKERNAME提取规则:默认NAME是连续非空白字符,如果你需要支持带空格的NAME,可以修改
nameEnd的判断逻辑 - 嵌套处理:通过
depth计数器精准匹配对应MARKER的ENDMARKER,不会被嵌套内的标记干扰 - 重复NAME处理:用
map[string][]string存储,同一个NAME的多个内容会被收集到切片中 - 灵活性:
GetMarkerContent函数可以快速根据NAME提取对应的所有内容
内容的提问来源于stack exchange,提问作者RWiggumUK
相关产品推荐
相关产品推荐

