You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
	}
}

代码说明

  1. MARKERNAME提取规则:默认NAME是连续非空白字符,如果你需要支持带空格的NAME,可以修改nameEnd的判断逻辑
  2. 嵌套处理:通过depth计数器精准匹配对应MARKER的ENDMARKER,不会被嵌套内的标记干扰
  3. 重复NAME处理:用map[string][]string存储,同一个NAME的多个内容会被收集到切片中
  4. 灵活性:GetMarkerContent函数可以快速根据NAME提取对应的所有内容

内容的提问来源于stack exchange,提问作者RWiggumUK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:32:46