
本文详解如何在 Go 中正确使用 regexp 删除纯空行(含仅含空格、制表符等空白字符的行),重点解决 ^ 和 $ 默认不按行匹配的问题,并提供健壮、跨平台的正则方案。
本文详解如何在 go 中正确使用 `regexp` 删除纯空行(含仅含空格、制表符等空白字符的行),重点解决 `^` 和 `$` 默认不按行匹配的问题,并提供健壮、跨平台的正则方案。
在 Go 的 regexp 包中,^ 和 $ 默认仅匹配整个输入字符串的开头和结尾,而非每行的起止位置——这与许多其他语言(如 Python 或 JavaScript)的默认行为不同。若要实现“按行匹配”,必须启用 multiline(多行)模式,即通过内联标志 (?m) 显式开启。
✅ 正确写法如下:
re := regexp.MustCompile(`(?m)^\s*$`)
其中 (?m) 启用多行模式,使 ^ 匹配每一行的开头,$ 匹配每一行的结尾(即换行符前的位置)。
⚠️ 但仅靠 (?m)^\s*$ 并不能完全满足“删除空行”的需求,原因有三:
-
\s包含\n、\r等垂直空白符,可能导致意外跨行匹配; -
$是零宽断言,不消耗换行符,因此替换后可能残留\n或\r\n; - 输入末尾若为纯空白行(无后续换行符),
^\s*$无法匹配,需额外处理。
? 推荐生产级正则表达式(兼顾 Unix/Linux (\n)、Windows (\r\n) 和旧 Mac (\r) 换行):
re := regexp.MustCompile(`(?m)^\s*$[\r\n]*|[\r\n]+\s*\z`)
表达式解析:
-
(?m)^\s*$[\r\n]*:匹配一行(^...\$),后接 0+ 个回车/换行符(清除该行及后续换行); -
|:或; -
[\r\n]+\s*\z:匹配末尾的换行符 + 可选空白 + 字符串绝对结尾\z(确保最后一行为空时也被清理)。
? 完整可运行示例:
package main
import (
"fmt"
"regexp"
)
func removeBlankLines(s string) string {
// 安全移除所有空行(含仅含空白符的行)及末尾残留换行
re := regexp.MustCompile(`(?m)^\s*$[\r\n]*|[\r\n]+\s*\z`)
return re.ReplaceAllString(s, "")
}
func main() {
input := `
hello
\t
world
`
result := removeBlankLines(input)
fmt.Printf("原始:\n%q\n", input)
fmt.Printf("结果:\n%q\n", result)
// 输出: "hello\nworld"
}
? 最佳实践建议:
- 若只需清理“逻辑空行”(忽略首尾空白),优先使用
strings.TrimSpace+strings.Split+ 过滤,更清晰可控; - 正则方案适用于需嵌入复杂文本处理流水线的场景;
- 避免使用
\s匹配行内空白——改用[ \t]更精准(排除\n\r); - 测试务必覆盖
\n、\r\n、\r及末尾无换行的边界情况。
综上,启用 (?m) 是关键起点,但真正鲁棒的空行清理需结合换行符显式匹配与字符串结尾锚点 \z,方能覆盖所有平台与边缘场景。











