【shell编程知识点汇总】第九章 HTML 清洗、多行合并与条件替换

目录

[一、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 

& 的典型应用场景:

  1. 给匹配内容加标记

    echo "price: 100" | sed 's/[0-9]+/[&]/'

    把文本里的第一个数字用方括号 [] 包起来。

    +:匹配一个或多个(+ 在 sed 里需要转义写成 +)

    &:引用匹配到的内容

    输出:price: [100]

  2. 重复匹配内容

    echo "abc" | sed 's/.*/& &/'

    输出:abc abc

    .*:正则,匹配整行所有字符

  3. 与反向引用的区别

  • &:引用整个匹配串

  • \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,$D

    • 4,$:从第 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。当命令前带有地址时,该命令仅对地址匹配的行生效。

执行逻辑:

  1. sed 逐行读取输入

  2. 检查当前行是否包含字符串 Error

  3. 如果包含 :执行 s/False/True/(将该行中的 False 替换为 True

  4. 如果不包含 :跳过 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 在处理日志过滤、配置修改、数据格式化等任务时极为高效。

相关推荐
AlienZHOU7 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc11 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师12 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen12 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒13 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow13 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林81813 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang8007813 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明13 小时前
第 6 章 组件进阶
前端·vue.js
江华森13 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端