
本文介绍如何使用正则表达式可靠地解析 discord 中格式化的 boss 刷新公告文本,提取名称、刷新时间窗口和倒计时信息,并映射到 go 结构体后序列化为标准 json 数据,适用于实时 webhook 或 websocket 推送场景。
本文介绍如何使用正则表达式可靠地解析 discord 中格式化的 boss 刷新公告文本,提取名称、刷新时间窗口和倒计时信息,并映射到 go 结构体后序列化为标准 json 数据,适用于实时 webhook 或 websocket 推送场景。
在构建 Discord 游戏服务器监控机器人时,常需从非结构化公告消息中提取关键事件数据(如 Boss 刷新时间)。原始消息以人工可读的 Markdown 风格呈现,但缺乏机器可解析的格式。为将其转化为可传输、可存储的结构化数据,推荐采用基于正则的逐行模式匹配策略——它兼顾简洁性、可维护性与鲁棒性,远优于手动字符串切分或脆弱的索引定位。
首先定义目标结构体(含 JSON 标签):
type Boss struct {
Name string `json:"name"`
SpawnWindowBegins string `json:"spawnWindowBegins"`
TimeTilWindow string `json:"timeTilWindow"`
}
核心解析逻辑围绕一条精心设计的正则表达式展开:^# ([^\n]+)\n([^|$|\[(?:Window begins|Window ends)\]\(([^)]+)\))
但注意:原始答案中给出的 ^(.*) = (.*)$?\z 实际适用于 键值对格式(如 Name = Red Nose),而题干提供的原始输入是 标题+时间行 的两行块结构。因此,真实场景需先按区块分割,再分别提取字段。以下是更贴合实际的完整实现:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
import (
"fmt"
"regexp"
"strings"
"encoding/json"
)
func parseBossAnnouncements(text string) []Boss {
// 按空行或连续 # 分隔多个 Boss 区块
blocks := regexp.MustCompile(`(?m)^# |\n\s*#\s+`).Split(text, -1)
var bosses []Boss
// 精确匹配每块:# 名称 + 时间行 + 可选括号说明
re := regexp.MustCompile(`^# ([^\n]+)\n([^|$|\[(?:Window begins|Window ends)\]\(([^)]+)\))`)
for _, block := range blocks {
block = strings.TrimSpace(block)
if block == "" {
continue
}
matches := re.FindStringSubmatchIndex([]byte(block))
if matches == nil {
continue // 跳过不匹配的噪声行
}
name := strings.TrimSpace(string(block[matches[0][0]+2 : matches[0][1]]))
timeLine := strings.TrimSpace(string(block[matches[1][0] : matches[1][1]]))
var timeTil string
if len(matches) > 2 && matches[2] != nil {
timeTil = strings.TrimSpace(string(block[matches[2][0] : matches[2][1]]))
} else if strings.Contains(timeLine, "<spawnable>") {
timeTil = "Spawnable"
} else {
timeTil = "Unknown"
}
bosses = append(bosses, Boss{
Name: name,
SpawnWindowBegins: strings.TrimSpace(timeLine),
TimeTilWindow: timeTil,
})
}
return bosses
}
// 使用示例
func main() {
raw := `# Red Nose
Mon, 06:45 EST - Mon, 15:15 EST <spawnable>
# Kutum
Mon, 09:25 EST - Mon, 17:55 EST [Window begins](in 2 hours)`
bosses := parseBossAnnouncements(raw)
data, _ := json.Marshal(bosses)
fmt.Println(string(data))
}</spawnable></spawnable>
✅ 关键注意事项:
-
避免过度依赖固定索引:原始消息中时间格式、括号内容可能存在微小变体(如
[Window begins]vs[Window starts]),正则应使用非贪婪匹配与可选分组; - 预处理增强健壮性:建议在解析前统一换行符、移除多余空格、过滤掉非公告类消息(如用户闲聊);
- 错误隔离:单条解析失败不应中断整个批次,应记录日志并跳过该区块;
-
时区标准化(进阶):EST 可转换为 RFC3339 时间戳,便于前端统一渲染,但需引入
time.ParseInLocation并注册时区; -
性能考量:对于高频消息(如每秒多条),可复用已编译的
*regexp.Regexp实例,避免重复regexp.MustCompile开销。
最终生成的 JSON 可直接通过 WebSocket 发送给前端应用,实现 Boss 刷新倒计时的实时可视化——结构清晰、字段明确、易于扩展,是游戏运维自动化中的典型文本→数据管道范式。










