
Golang 中默认 . 不匹配换行符,导致多行文本中的正则无法捕获跨行内容;需添加 (?s) 标志启用单行模式(dotall),而非仅依赖 (?m) 多行模式。
golang 中默认 `.` 不匹配换行符,导致多行文本中的正则无法捕获跨行内容;需添加 `(?s)` 标志启用单行模式(dotall),而非仅依赖 `(?m)` 多行模式。
在 Go 的 regexp 包中,正则标志 (?m)(multiline mode)仅影响 ^ 和 $ 的行为(使其匹配每行起止),并不改变 . 的匹配范围——它依然默认跳过 \n、\r 等换行符。这正是问题中正则 (?m)
✅ 正确做法是使用 (?s)(single-line / dotall 模式),它让 . 可匹配包括换行符在内的任意字符:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
func main() {
r := regexp.MustCompile(`(?s)<think>(.*?)</think>`) // 同时启用 dotall + 非贪婪
const s = `That is
<think>
FOOBAR
</think>`
matches := r.FindStringSubmatch([]byte(s))
if len(matches) > 0 {
fmt.Printf("Matched content: %s\n", strings.TrimSpace(string(matches[1:]))) // 去掉 <think>...</think> 外层标签
}
}
⚠️ 注意事项:
- (?s) 替代 (?m):本例无需 (?m),仅 (?s) 即可解决跨行匹配问题;
- 使用非贪婪 .*?:避免“贪婪匹配”导致多个
标签间被整体捕获(例如 ... ...A ...B ... 会错误匹配 AB)。.*? 确保最短匹配,精准提取每个标签内的内容; - 输入类型一致性:regexp.MustCompile 返回的 *Regexp 对 string 和 []byte 提供不同方法(如 FindStringSubmatch 接收 string,但返回 []byte;若处理大文本建议统一用 []byte 避免重复转换);
- 边界安全:若标签可能嵌套或含转义,正则将不可靠,此时应改用 HTML 解析器(如 golang.org/x/net/html)。
总结:Go 正则的 . 默认不匹配换行符是高频陷阱;牢记 (?s) 是多行内容捕获的关键开关,配合 .*? 实现安全、精准的标签内提取。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










