Linux 文本三剑客(2)sed命令的使用

📅 2026/8/15 9:17:44
Linux 文本三剑客(2)sed命令的使用
Linux 文本三剑客之 sed流编辑器从入门到精通一、sed 引言与历史1.1 sed 是什么sedstreameditor流编辑器是一个使用简单紧凑的编程语言来解析和转换文本的 Unix 实用程序。它最显著的特点是对输入只做一次遍历即可完成编辑因此效率极高。与交互式编辑器不同sed 尤其擅长在管道中过滤和转换文本——这也是它与其他编辑器最本质的区别。1.2 sed 在文本三剑客中的定位工具核心能力典型场景复杂度grep按模式搜索并输出匹配行日志过滤、关键字查找⭐ 入门级sed对文本流进行替换/删除/插入批量替换、行编辑⭐⭐ 中级awk按字段处理结构化文本支持编程逻辑报表生成、数据提取⭐⭐⭐ 高级grep 更适合单纯的查找sed 更适合编辑匹配到的文本awk 更适合对结构化文本做字段级分析。1.3 历史由来sed 由贝尔实验室的李·E·麦克马洪Lee E. McMahon于 1973 年至 1974 年开发现在几乎所有操作系统都可以使用。sed 基于交互式编辑器ed1971 年和更早的qed1965-66 年的脚本功能是最早支持正则表达式的工具之一至今仍广泛用于文本处理特别是替换命令。二、sed 工作原理sed 的工作方式是逐行处理从文件或管道中读取一行将当前行存入临时缓冲区——模式空间Pattern Space用 sed 命令对模式空间中的内容进行处理处理完成后将缓冲区的内容输出到屏幕读取下一行重复上述过程直到文件末尾逐行处理带来的优势性能极高sed 在读取大文件时不会出现卡顿内存友好与 vi 等编辑器一次性加载整个文件不同sed 每次只处理一行管道友好可以从标准输入读取与管道完美配合如果使用 vi 打开几十兆上百兆的文件会明显卡顿——因为 vi 是一次性将整个文件加载到内存。而 sed 一行一行地处理打开速度和执行速度都非常快。三、sed 的作用sed 可依照脚本的指令来处理、编辑文本文件主要能力包括✅增删改查新增行、删除行、替换文本、查找匹配✅取行按行号或正则表达式提取指定行✅替换支持正则替换是 sed 最常用的功能✅自动化编辑简化对文件的反复操作编写转换程序典型应用场景批量替换在多个文件中统一替换配置项格式转换将日期格式从 MM/DD/YYYY 转为 YYYY-MM-DD✂️文本提取从日志中提取特定时间段的内容模板处理用脚本自动生成配置文件或报告四、sed 语法格式sed[OPTIONS]SCRIPT[INPUTFILE...]或使用脚本文件sed[OPTIONS]-fSCRIPT_FILE[INPUTFILE...]参数说明参数说明OPTIONS可选的命令行选项控制 sed 的行为SCRIPTsed 命令序列用单引号括起来SCRIPT_FILE包含 sed 脚本的文件通过-f指定INPUTFILE要处理的输入文件可指定多个省略时从标准输入读取五、sed 常用选项详解选项长选项说明-n--quiet,--silent静默模式不自动输出模式空间的内容。只有显式使用p命令时才输出-e SCRIPT--expressionSCRIPT添加一个 sed 命令到待执行的命令序列中。可多次使用-f FILE--fileFILE从 FILE 中读取 sed 脚本-i--in-place直接修改文件原地编辑而非输出到屏幕。可加后缀名创建备份如-i.bak-r--regexp-extended使用扩展正则表达式EREGNU sed 特有。等价于-E-h--help显示帮助信息-V--version显示版本信息最重要的选项-n控制输出和-i原地编辑。-n几乎总是和p命令配合使用-i是批量修改文件的利器但用之前建议先不加-i预览效果。六、sed 地址与动作6.1 地址表示法sed 命令可以指定地址以控制对哪些行执行操作。地址可以是地址类型格式示例单行号Nsed 5p—— 第 5 行行号范围N,Msed 1,5p—— 第 1 到 5 行正则表达式/pattern/sed /error/p—— 匹配 “error” 的行最后一行$sed $p—— 最后一行取反!sed /error/!p—— 不匹配 “error” 的行6.2 基本动作动作说明示例p打印输出模式空间的内容sed -n 1,5p filed删除模式空间的内容立即开始下一轮循环sed 1d files替换最常用格式s/正则/替换/修饰符sed s/old/new/g filea在指定行后面追加文本sed 3a\新内容 filei在指定行前面插入文本sed 3i\新内容 filec替换指定行sed 3c\新内容 filey逐字符替换类似tr命令sed y/abc/ABC/ file替换修饰符修饰符含义g全局替换替换行内所有匹配而非仅第一个数字只替换第 N 个匹配如s/old/new/2p当发生替换时打印该行与-n配合w FILE将替换成功的行写入 FILE七、sed 实战实例以下实例基于 Ubuntu 18.04 演示。建议先创建测试文件跟随操作。7.1 准备测试文件创建一个名为distros.txt的文本文件内容为 Linux 发行版名称、版本号和发布日期[melinuxbox ~]$catdistros.txtEOF Fedora 10 11/25/2008 Ubuntu 8.04 04/24/2008 SUSE 10.3 10/04/2007 Fedora 8 11/08/2007 Ubuntu 6.10 10/26/2006 Fedora 7 05/31/2007 SUSE 11.0 06/19/2008 Ubuntu 7.10 10/18/2007 Ubuntu 7.04 04/19/2007 Fedora 6 10/24/2006 Fedora 9 05/13/2008 Ubuntu 6.06 06/01/2006 SUSE 10.2 12/07/2006 Ubuntu 8.10 10/30/2008 Fedora 5 03/20/2006 SUSE 10.1 05/11/2006 EOF7.2 按行号取行p命令输出distros.txt文件的第 1-5 行[melinuxbox ~]$sed-n1,5pdistros.txt Fedora1011/25/2008 Ubuntu8.0404/24/2008 SUSE10.310/04/2007 Fedora811/08/2007 Ubuntu6.1010/26/2006关键理解-n抑制了默认输出p命令显式打印了匹配的行。如果不加-nsed 会先输出所有行再额外输出匹配的行导致匹配行出现两次。7.3 按正则匹配地址与否定查找所有包含 “SUSE” 的行[melinuxbox ~]$sed-n/SUSE/pdistros.txt SUSE10.212/07/2006 SUSE11.006/19/2008 SUSE10.310/04/2007 SUSE10.105/11/2006在地址末尾添加!进行取反——查找不包含“SUSE” 的行[melinuxbox ~]$sed-n/SUSE/!pdistros.txt Fedora1011/25/2008 Ubuntu8.0404/24/2008 Fedora811/08/2007 Ubuntu6.1010/26/2006 Fedora705/31/2007 Ubuntu7.1010/18/2007 Ubuntu7.0404/19/2007 Fedora610/24/2006 Fedora905/13/2008 Ubuntu6.0606/01/2006 Ubuntu8.1010/30/2008 Fedora503/20/20067.4 删除行d命令删除第 1 到 3 行输出剩余内容[melinuxbox ~]$sed1,3ddistros.txt Fedora811/08/2007 Ubuntu6.1010/26/2006...被删除的行不会出现在输出中但原文件未被修改除非使用-i选项。7.5 替换与逆参照s命令核心这是 sed 最强大的功能。distros.txt中的日期格式是MM/DD/YYYY我们希望将其改为YYYY-MM-DD。第一步构造正则表达式日期在行尾格式为两位数字/两位数字/四位数字。在 BRE基本正则表达式中[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}$⚠️ 注意sed 默认使用 BRE{}需要用反斜杠转义写成\{2\}。如果使用-EERE 模式则直接写{2}即可。第二步用括号分组捕获用\(和\)将月份、日期、年份分别括起来形成三个子表达式\([0-9]\{2\}\)/\([0-9]\{2\}\)/\([0-9]\{4\}\)$\1— 月份第一个子表达式\2— 日期第二个子表达式\3— 年份第三个子表达式第三步构造替换字符串用逆参照back-reference重新排列为\3-\1-\2年-月-日[melinuxbox ~]$seds/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/distros.txt SUSE10.22006-12-07 Fedora102008-11-25 SUSE11.02008-06-19 Ubuntu8.042008-04-24 Fedora82007-11-08 SUSE10.32007-10-04 Ubuntu6.102006-10-26 Fedora72007-05-31 Ubuntu7.102007-10-18 Ubuntu7.042007-04-19 SUSE10.12006-05-11 Fedora62006-10-24 Fedora92008-05-13 Ubuntu6.062006-06-01 Ubuntu8.102008-10-30 Fedora52006-03-20逆参照总结\1到\9分别引用正则表达式中第 1 到第 9 个\(...\)分组。这是 sed 替换中最强大的技巧之一。等价的 ERE 写法使用-E选项更简洁sed-Es/([0-9]{2})\/([0-9]{2})\/([0-9]{4})$/\3-\1-\2/distros.txt在 ERE 模式下()、{}无需转义代码更清晰。推荐在较新的脚本中使用-E。7.6 全局替换g修饰符s命令默认只替换每行的第一个匹配。使用g修饰符可以替换所有匹配# 默认只替换每行第一个匹配[melinuxbox ~]$echoaabbbccc|seds/b/B/aaBbbccc# 加 g替换所有匹配[melinuxbox ~]$echoaabbbccc|seds/b/B/gaaBBBccc7.7 使用不同分隔符当替换内容本身包含/时可以换用其他分隔符如#、、|避免转义# 传统写法需要转义斜杠seds/\/usr\/local\/bin/\/opt\/bin/gfile# 改用 # 分隔符清晰多了seds#/usr/local/bin#/opt/bin#gfiles命令中第一个出现的字符即为分隔符s、s###、s|||都合法。八、sed 脚本8.1 编写 sed 脚本文件对于复杂的编辑任务建议将多个 sed 命令写入脚本文件通过-f选项执行。下面我们编写一个脚本用于生成发行版报告添加标题、转换日期格式、将发行版名称转为大写。创建distros.sed脚本文件[melinuxbox ~]$catdistros.sedEOF # sed 脚本生成 Linux 发行版报告 1 i\ \ Linux Distributions Report\ s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ EOF脚本文件内容详解[melinuxbox ~]$cat-ndistros.sed1# sed 脚本生成 Linux 发行版报告231i\4\5Linux Distributions Report\67s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/8y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/逐行说明行号说明第 1 行注释。以#开头可放在脚本任意位置第 2 行空行提高可读性第 3-5 行1 i\表示在第 1 行之前插入文本。i命令后的文本每行必须以\结尾连行符最后一行为普通回车。这里插入了一个空行和标题行第 7 行日期格式转换年-月-日。因为前面没有地址对每一行都执行第 8 行y命令逐字符替换将小写字母转为大写。同样对所有行生效⚠️连行符规则\后紧跟回车符两者之间不允许有空白字符。a追加、i插入、c替换命令都支持多行文本除最后一行外每行都必须以连行符结尾。8.2 运行脚本[melinuxbox ~]$sed-fdistros.sed distros.txt Linux Distributions Report SUSE10.22006-12-07 FEDORA102008-11-25 SUSE11.02008-06-19 UBUNTU8.042008-04-24 FEDORA82007-11-08 SUSE10.32007-10-04 UBUNTU6.102006-10-26 FEDORA72007-05-31 UBUNTU7.102007-10-18 UBUNTU7.042007-04-19 SUSE10.12006-05-11 FEDORA62006-10-24 FEDORA92008-05-13 UBUNTU6.062006-06-01 UBUNTU8.102008-10-30 FEDORA52006-03-20九、常用实战技巧9.1 原地修改文件# 直接修改文件危险操作建议先预览sed-is/old/new/gfile.txt# 带备份修改前自动创建 file.txt.baksed-i.baks/old/new/gfile.txt9.2 删除空行和注释行# 删除空行sed/^$/dconfig.conf# 删除以 # 开头的注释行sed/^#/dconfig.conf# 同时删除空行和注释行sed/^$/d; /^#/dconfig.conf9.3 提取日志中的时间范围# 提取 10:00 到 11:00 之间的日志sed-n/10:00/,/11:00/p/var/log/syslog9.4 在匹配行前后插入内容# 在匹配 [ERROR] 的行前插入分隔线sed/\[ERROR\]/i\-------- ERROR --------app.log# 在匹配行后追加sed/\[ERROR\]/a\-------- END --------app.log9.5 多命令组合# 使用 -e 多次指定命令或使用分号分隔sed-es/foo/bar/g-es/baz/qux/gfile.txt# 等价写法seds/foo/bar/g; s/baz/qux/gfile.txt十、sed 速查备忘卡# ┌─────────────────────────────────────────────────┐ # │ SED 速查备忘卡 │ # ├─────────────────────────────────────────────────┤ # │ sed -n 5p file 打印第 5 行 │ # │ sed -n 1,5p file 打印第 1-5 行 │ # │ sed -n /pat/p file 打印匹配行 │ # │ sed -n /pat/!p file 打印不匹配行 │ # │ sed s/old/new/ file 替换每行第一个匹配 │ # │ sed s/old/new/g file 全局替换 │ # │ sed s/old/new/2 file 替换每行第 2 个匹配 │ # │ sed /pat/d file 删除匹配行 │ # │ sed 1,3d file 删除第 1-3 行 │ # │ sed /^$/d file 删除空行 │ # │ sed 3a\text file 在第 3 行后追加 │ # │ sed 3i\text file 在第 3 行前插入 │ # │ sed -i s/old/new/g f 原地修改无备份 │ # │ sed -i.bak s/old/new/g 原地修改.bak备份 │ # │ sed -E s/.../.../ f 扩展正则ERE │ # │ sed -f script.sed file 执行脚本文件 │ # │ sed y/abc/ABC/ file 逐字符替换 │ # │ sed -n 10,20p file 打印第 10-20 行 │ # └─────────────────────────────────────────────────┘十一、小结sed 是 Linux 文本处理三剑客中承上启下的关键角色——比 grep 更强大比 awk 更轻量。回顾本文要点逐行处理是 sed 的核心设计——模式空间 一次遍历高效且内存友好地址 动作是 sed 的基本语法模式——地址决定对哪些行动作决定做什么s命令是 sed 的灵魂——配合正则表达式和逆参照可以实现复杂的文本转换BRE vs ERE——默认使用 BRE{}、()需转义使用-E切换到 ERE 更简洁脚本文件让 sed 从单行工具升级为编程语言——多命令组合实现自动化报告生成-i是双刃剑——方便但危险建议先预览再原地修改或使用-i.bak保留备份。延伸阅读《The Linux Command Line》TLCL第 21 章 —— 文本处理工具全面讲解man sed—— 最权威的官方文档info sed—— GNU sed 的详细手册包含更多高级用法如保持空间、分支命令等本文参考 TLCLThe Linux Command Line第 21 章文本处理的讲解思路结合 sed 专题进行了系统梳理与扩展。