
本文介绍在 go 中高效过滤掉包含指定子字符串的文本行,通过正则表达式实现类似 ruby `reject { |r| r.include? ‘substring’ }` 的语义,并兼顾跨平台换行符(`n`/`rn`)和边界匹配准确性。
在 go 中处理文本行过滤时,由于标准库不提供类似 Ruby 的链式 split → reject → join 高阶操作,需结合 strings 包或正则表达式手动实现。最简洁、鲁棒的方式是使用 regexp 包配合多行模式((?m)),精准匹配整行并移除。
以下是一个完整可运行的示例:
package main import ( "fmt" "regexp" ) func removeLinesContaining(s, substr string) string { // 构造正则:多行模式下,匹配以任意换行符开头(可选)、包含 substr 的整行(含其后的换行符) // 使用 [rn]+ 适配 n 和 rn;^ 和 $ 在 (?m) 下匹配行首/行尾 pattern := "(?m)^.*" + regexp.QuoteMeta(substr) + ".*$[rn]*" re := regexp.MustCompile(pattern) return re.ReplaceAllString(s, "") } func main() { input := `aaaaa bbbb cc substring ddd eeee ffff gggrnhh substring iirnjjj` result := removeLinesContaining(input, "substring") fmt.Println(result) }
输出:
aaaaa bbbb eeee ffff ggg jjj
✅ 关键要点说明:
- (?m) 启用多行模式,使 ^ 和 $ 分别匹配每行开头与结尾(而不仅是整个字符串首尾);
- [rn]* 匹配行尾换行符(支持 n、rn 或孤立 r),* 确保末尾无换行符的行也能被正确清理;
- regexp.QuoteMeta(substr) 对子字符串进行转义,防止其中含正则元字符(如 .、*、[)导致意外匹配;
- 若输入为 []byte,可改用 re.ReplaceAll(s, []byte(“”)),避免字符串与字节切片间反复转换。
⚠️ 注意事项:
- 正则方式简洁,但对超大文本(GB 级)可能存在性能开销;此时建议逐行扫描(strings.Split + strings.Contains + strings.Join),内存可控且逻辑更直观;
- 若需保留原始换行符一致性(如统一转为 n),可在最后调用 strings.ReplaceAll(result, “rn”, “n”)。
综上,正则方案适合中小规模文本、追求代码简洁性;流式逐行处理更适合大数据量或严格内存控制场景。两者皆可封装为通用函数,按需选用。