目录
[一、HTML 标签清洗:剥离尖括号内容](#一、HTML 标签清洗:剥离尖括号内容)
[二、多行合并:N 命令与换行符替换](#二、多行合并:N 命令与换行符替换)
[三、逻辑取反:! 的否定语义](#三、逻辑取反:! 的否定语义)
[四、匹配整体引用:& 的替身魔法](#四、匹配整体引用:& 的替身魔法)
在文本处理中,sed 不仅是简单的查找替换工具,更是能够处理结构化文本、执行条件逻辑的行级编辑器。本文针对六个高阶场景------从 HTML 标签清洗到地址限定替换------深入解析其内部机制,帮助你日志分析、数据清洗和配置管理。
一、HTML 标签清洗:剥离尖括号内容
问题: sed 's/<[^>]*>//g' 这个正则模式主要用来去除什么?
解析:
这是 sed 中经典的 HTML/XML 标签去除 模式,用于将文本中的所有 HTML 标签剥离,仅保留纯文本内容。
正则拆解:
| 模式 | 含义 |
|---|---|
< |
匹配左尖括号(标签起始) |
[^>]* |
匹配从当前位置开始,一直到第一个 > 之前的所有内容 (不含 > 本身)。 |
> |
匹配右尖括号(标签结束) |
// |
替换为空(删除) |
g |
全局标志,处理行内所有标签 |
工作原理:
[^>]* 是一个否定字符类 ,它贪婪地匹配标签内的所有属性、样式和文本,直到遇到第一个 > 为止。配合 g 标志,一行内出现的多个标签都会被依次移除。
示例:
echo '<p class="intro">Hello <b>World</b>!</p>' | sed 's/<[^>]*>//g'
# 输出:Hello World!
#这里 s/<[^>]*>//g:把所有 HTML 标签替换成空字符串
#HTML 标签比如:<p>、<p class="intro">、<b>、</b>、</p> 全都能匹配到。
⚠️ 注意事项:
此模式适用于简单、格式规范 的 HTML。对于嵌套复杂、包含 > 在属性值中(如 data-val="a>b")或跨行标签的情况,sed 的单行处理能力可能力不从心,此时建议使用专门的 HTML 解析器。
二、多行合并:N 命令与换行符替换
问题: sed 'N; s/\n/ /' 其中的 N 命令和 \n 的替换实现了什么样的行操作?
解析:
该命令实现了将相邻的两行合并为一行 ,并用空格替代原有的换行符。
核心机制:
-
N(Next) :将输入流的下一行 追加到当前模式空间(pattern space),两行之间以换行符\n分隔 -
s/\n/ /:将模式空间中的换行符替换为空格,完成行合并
执行流程示例:
# 输入:
# Hello
# World
sed 'N; s/\n/ /' file.txt
# 输出:
# Hello World
进阶理解:
N 是 sed 处理多行模式空间 的关键命令。默认情况下 sed 逐行处理,但 N 允许你将多行加载到同一个模式空间进行跨行操作。类似的命令还有:
-
P:打印模式空间中第一行(到第一个\n为止) -
D:删除模式空间中第一行,并重新开始循环
循环合并多行:
如果需要将所有行合并为一行,可以配合标签实现循环:
sed ':a; N; s/\n/ /; ta' file.txt
#:a定义一个标签 a(相当于循环的起点)。
三、逻辑取反:! 的否定语义
问题: sed '/foo/!d' file.txt 中的感叹号 ! 表示什么逻辑?
解析:
! 表示逻辑取反(negation),即"对不匹配地址的行执行后续命令"。
完整解读:
-
/foo/:地址条件,匹配包含字符串foo的行 -
!:否定该地址条件 -
d:删除命令
因此,/foo/!d 的含义是:删除所有不包含 foo 的行 ,最终只保留包含 foo 的行。
等价命令:
sed '/foo/!d' file.txt
# 完全等价于:
sed -n '/foo/p' file.txt
#默认 sed 会输出所有行
#加 -n = 只输出我们指定的行
#p print = 打印匹配到的行
! 的通用性:
! 可以应用于任何命令和地址组合,例如:
sed '5!s/foo/bar/' # 除第5行外,其他行中的 foo 替换为 bar
sed '$!d' # 删除除最后一行外的所有行(仅保留最后一行)
#$ :匹配最后一行 ! :取反,不是最后一行 d :delete,删除当前行
四、匹配整体引用:& 的替身魔法
问题: 解释 sed 's/./& /g' 中符号 & 代表什么内容?
解析:
& 在 sed 的替换字符串中表示整个正则表达式匹配到的完整文本(即匹配模式的"镜像")。
命令拆解:
-
.:匹配任意单个字符(包括空格、标点等) -
&:在替换部分,&被替换为刚才匹配到的那个字符,后面再加一个空格 -
g:全局执行,对每行中每个字符都操作
效果演示:
echo "Hello" | sed 's/./& /g'
# 输出:H e l l o
& 的典型应用场景:
-
给匹配内容加标记:
echo "price: 100" | sed 's/[0-9]+/[&]/'
把文本里的第一个数字用方括号 [] 包起来。
+:匹配一个或多个(+ 在 sed 里需要转义写成 +)
&:引用匹配到的内容
输出:price: [100]
-
重复匹配内容:
echo "abc" | sed 's/.*/& &/'
输出:abc abc
.*:正则,匹配整行所有字符
-
与反向引用的区别:
-
&:引用整个匹配串 -
\1,\2...:引用捕获组(括号内的部分)
五、精准定位:只输出最后一行
问题: sed -n '$p' file.txt 只会输出文件的哪一部分?
解析:
该命令仅输出文件的最后一行。
符号解析:
| 符号 | 含义 |
|---|---|
-n |
静默模式,抑制默认的逐行打印行为 |
$ |
特殊地址,代表最后一行(Last Line) |
p |
显式打印命令 |
工作流程:
sed 逐行读取文件,-n 确保不自动输出任何内容。当读取到最后一行时,$ 地址匹配成功,触发 p 命令将其打印。
等效命令对比:
sed -n '$p' file.txt # sed 方式
tail -n 1 file.txt # tail 方式
awk 'END{print}' file.txt # awk 方式
扩展:倒数第 N 行
sed 本身没有直接支持倒数第 N 行的内置地址,但可以通过保持空间(hold space)或结合其他命令实现:
# 输出倒数第3行
sed -n ':a; N; 4,$D; ba' file.txt
-
-n安静模式,不自动输出任何行。 -
:a定义一个标签 a,循环的起点。 -
N读取下一行,追加到模式空间(缓冲区)。 -
4,$D4,$:从第 4 行 到最后一行D:删除模式空间第一行- 意思:只要缓冲区里 ≥4 行,就删掉最旧的那一行
-
ba无条件跳回标签 a,继续循环。 -
读第 1 行 → 缓存:
[1] -
读第 2 行 → 缓存:
[1,2] -
读第 3 行 → 缓存:
[1,2,3] -
读第 4 行 → 缓存≥4 行 → 删第 1 行 → 缓存:
[2,3,4] -
读第 5 行 → 缓存≥4 行 → 删第 2 行 → 缓存:
[3,4,5] -
... 一直到文件结束
-
最后缓存里剩下的就是 最后 3 行
六、地址限定替换:条件化编辑
问题: 在 sed '/Error/s/False/True/' 中,替换操作 s 是在所有行执行,还是受限于前面的地址?
解析:
替换操作受限于前面的地址 ,只有匹配 /Error/ 的行才会执行 s/False/True/。
地址-命令结构:
sed 的命令格式为 [address[,address]]command。当命令前带有地址时,该命令仅对地址匹配的行生效。
执行逻辑:
-
sed 逐行读取输入
-
检查当前行是否包含字符串
Error -
如果包含 :执行
s/False/True/(将该行中的False替换为True) -
如果不包含 :跳过
s命令,该行原样输出(除非有其他命令)
示例演示:
# 输入:
# Status: OK, Result: False
# Status: Error, Result: False
# Status: Warning, Result: False
sed '/Error/s/False/True/' file.txt
# 输出:
# Status: OK, Result: False
# Status: Error, Result: True
# Status: Warning, Result: False
复合地址应用:
地址限定可以与范围、正则、行号灵活组合:
sed '5,10s/foo/bar/' # 仅第5到10行执行替换
sed '/BEGIN/,/END/s/x/y/' # 仅BEGIN到END范围内的行执行替换
sed '/^#/!s/^/ /' # 对非注释行缩进两个空格
# /^#/:匹配以 # 开头的注释行
# !:取反 → 不是注释行
# s/^/ /:行首插入两个空格
总结速查表
| 问题 | 核心知识点 | 一句话总结 |
|---|---|---|
| 1 | s/<[^>]*>//g |
删除 HTML/XML 标签,提取纯文本 |
| 2 | N; s/\n/ / |
加载下一行到模式空间,将换行转为空格合并行 |
| 3 | /foo/!d |
! 取反,只保留匹配行,删除其余行 |
| 4 | s/./& /g |
& 代表完整匹配串,给每个字符后加空格 |
| 5 | -n '$p' |
-n 配合 $p,精确输出文件最后一行 |
| 6 | /Error/s/.../ |
地址限定命令作用域,仅匹配行执行替换 |
结语
sed 的魅力在于其地址-命令模型的简洁与强大。通过地址筛选目标行,再通过命令执行精确编辑,这种"先定位、后操作"的范式,使得 sed 在处理日志过滤、配置修改、数据格式化等任务时极为高效。