【shell编程知识点汇总】第九章 HTML 清洗、多行合并与条件替换
目录
一、HTML 标签清洗:剥离尖括号内容
二、多行合并: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 在处理日志过滤、配置修改、数据格式化等任务时极为高效。
