sed 输出变了,文件就改了吗?18 项实测看清打印、替换与备份

举报
yd_241387476 发表于 2026/11/02 09:41:25 2026/11/02
【摘要】 在华为云 KooLabs 的 GNU sed 4.9 中完成 18 项断言,区分默认打印、显式打印、替换范围、终端输出与磁盘文件,并验证 -i.bak 的备份行为。

练习文本处理时,最容易误判的现象是:终端已经显示替换后的内容,于是以为原文件也被修改。另一个常见困惑是:明明只让 sed 打印第一行,为什么整个文件都出现了,而且第一行还重复?

这次围绕华为云 KooLabs 的「Linux 文本“三剑客” — SED」实验目标,在实验操作桌面的 GNU sed 4.9 中,用自建文本样例做了 18 项断言。练习集中在 p、d、s、行地址和带备份的原地修改,文件写入只发生在临时目录。下面记录的是实际运行结果,不代表官方实验报告的评分,也不涉及修改系统配置。

先把输入、处理结果和磁盘文件分开看

准备五行样例,文件名使用新的练习文件:

printf '%s\n' alpha beta gamma delta epsilon > sample.txt

这份文件提供三个互相独立的检查对象:输入原文、sed 输出到终端的内容、命令运行后磁盘里保存的内容。测试时同时检查三者,比单看终端截图更容易发现误判。

例如运行:

sed '1,4d' sample.txt

终端只显示 epsilon。紧接着读取 sample.txt,仍然能看到完整五行。这里删除的是本次处理输出中的第 1 至 4 行;这条命令没有把修改写回原文件。实测脚本分别断言了输出等于一行、源文件仍等于原始五行,两项都通过。

第一行重复,来自两次输出

同样的五行输入,运行 sed '1p' sample.txt,结果是六行:alpha 出现两次,随后依次是 beta、gamma、delta、epsilon。

原因可以按执行过程理解:第一行命中 1p,显式打印一次;正常处理周期结束时还会自动打印一次。其余行没有命中 p,但仍有默认输出。

对照命令是:

sed -n '1p' sample.txt

这次只得到 alpha 一行。-n 控制默认打印,p 控制明确选中的打印操作。两者不是同一个开关。GNU 手册的 “Command-Line Options”章节 也说明了 -n 与自动打印的关系。

如果需求是“只要符合条件的行”,先写出筛选条件,再决定是否关闭默认打印,通常比看输出后反复加参数更清晰。

行范围、分离地址和正则,得到的是不同集合

本次样例中,以下结果都经过断言验证:

命令中的脚本 配合选项 输出
2,4p -n beta、gamma、delta
1p;4p -n alpha、delta
1~2p -n alpha、gamma、epsilon
/^g/p -n gamma
/beta/!d 无 beta
$d 无 前四行

逗号表达连续区间,分号连接独立指令。1~2 是本次 GNU sed 环境中的步进行地址,不能仅凭这次测试就断言其他 sed 实现行为相同;官方 GNU sed 手册“Numeric Addresses”章节 将这种写法列为 GNU 扩展。

实际维护脚本时,还应记录系统和 sed 实现。这里只验证了 GNU sed 4.9,没有做 macOS/BSD sed 的兼容性测试。

s 的默认范围是每行第一次匹配

把输入缩小成 2023 2023 2023 一行后,三种脚本的差异很直观:

s/2023/X/     -> X 2023 2023
s/2023/X/g    -> X X X
s/2023/X/2    -> 2023 X 2023

三种结果分别对应每行首次匹配、每行所有匹配、每行第二次匹配。这些是本次相同输入的直接运行结果。要批量处理日志或配置,先用一行包含多个重复词的样例做对照,能迅速发现“只替换了一部分”的范围错误。

需要写回时,验证结果和备份

在临时目录里重新创建完整的五行 sample.txt 后,执行:

sed -i.bak '1,4d' sample.txt

这次验证了两件事:sample.txt 只剩 epsilon;sample.txt.bak 保留原始五行。两项断言都通过。测试脚本随后退出临时目录并自动清理自建样例,没有碰系统配置文件。

对于真实文件,建议先输出到另一个临时结果文件并查看差异,确认修改范围后再决定写回方式。备份后也应读取备份检查内容,不能只凭文件名存在就认为可以恢复。固定的 .bak 名称也不适合充当长期、多版本的备份策略。

尤其不要把“减少终端输出”与“保留文件内容”混为一谈。GNU 手册专门提醒:-n 与 -i 组合使用而缺少必要打印操作时,可能把原文件改为空文件。本次没有对真实文件尝试这种操作。

本次实测覆盖与边界

18 项断言覆盖了默认打印叠加 p、关闭默认打印、连续行与分离地址、GNU 步进地址、正则筛选、删除范围、取反条件、末行删除、三种替换范围、整行替换、追加模拟主机记录,以及普通输出和带备份写回后的文件内容。

断言脚本使用 Python 的 subprocess 调用实际 sed,用精确字符串比较验证结果,而不是自己重新实现 sed。最终终端输出为 SUMMARY: 18 assertions passed。这些小测试说明了本次环境和样例下的行为;它们没有覆盖链接文件、文件权限、并发写入、所有编码、所有平台或复杂多行脚本。

这次练习最有用的检查习惯是:每次都明确自己正在观察终端输出、内存中的处理结果,还是磁盘文件。确认这三个对象以后,再讨论“已经替换”“已经删除”或“可以恢复”,结论会准确得多。

实验入口:华为云 Linux SED 实验。本文由 AI 辅助整理,命令结果来自上述沙箱实测。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。