Linux 下 sed 命令的核心用法与实战指南
概述
sed(Stream Editor,流编辑器)是 Linux 系统中一款高效的文本处理工具,其核心能力是通过脚本指令自动化处理文本文件,无需手动打开编辑界面即可完成批量修改、过滤、转换等操作。
根据 man 手册的官方定义,sed 是 “stream editor for filtering and transforming text”,即用于过滤和转换文本的流编辑器。它的典型应用场景包括:
- 自动编辑单个或多个文本文件
- 简化对文件的重复性操作(如批量替换固定字符)
- 编写文本格式转换程序(如日志格式标准化)
- 配合管道(|)处理其他命令的输出结果
sed 核心参数解析
sed 的参数用于控制命令的执行模式,常用核心参数如下表所示,清晰区分参数作用与使用场景:
参数 | 完整写法 | 核心作用 | 适用场景 |
---|---|---|---|
-n | - | 抑制模式空间的自动打印 | 仅显示匹配或处理后的内容(需配合 p 命令) |
-e | --expression=script | 多点编辑 | 一次执行多个 sed 命令(如同时删除 + 替换) |
-f | --file=/PATH/TO/SCRIPT | 从文件读取命令 | 命令较多时,将指令写入脚本文件批量执行 |
-r | --regexp-extended | 支持扩展正则表达式 | 无需对 +、?、() 等符号转义(同 -E) |
-i | --in-place[=SUFFIX] | 直接编辑原文件 | 需修改源文件时使用(加后缀可备份,如 -i.bak) |
sed 地址:定位要处理的行
sed 通过 “地址” 指定需要处理的文本行,地址格式决定了操作的范围,是精准处理文本的关键。
地址类型 | 格式示例 | 作用说明 |
---|---|---|
空地址 | 无 | 对文件所有行执行操作 |
单地址 | 5 | 仅处理第 5 行 |
单地址 | /error/ | 处理所有包含 “error” 模式(正则匹配)的行 |
地址范围 | 3,7 | 处理第 3 行到第 7 行(含首尾) |
地址范围 | 5,+3 | 处理第 5 行及后续 3 行(共 4 行:5/6/7/8) |
地址范围 | 2,/EOF/ | 从第 2 行开始,直到匹配 “EOF” 的行结束 |
地址范围 | /start/,/end/ | 从匹配 “start” 的行开始,到匹配 “end” 的行结束 |
地址范围 | $ | 仅处理文件的最后一行($ 表示行尾) |
步进(间隔) | 1~2 | 处理所有奇数行(从第 1 行开始,步长 2) |
步进(间隔) | 2~2 | 处理所有偶数行(从第 2 行开始,步长 2) |
sed 基础命令:实现核心操作
sed 命令需配合 “地址” 使用,定义对定位行的具体操作,常用基础命令如下:
命令 | 语法格式 | 作用说明 |
---|---|---|
d | [地址]d | 删除定位到的行(不保留到输出) |
p | [地址]p | 打印模式空间中的内容(需配合 -n 抑制默认输出) |
a | [地址]a \text | 在定位行后面追加文本 “text”,支持 \n 换行(如 a hello\nworld) |
i | [地址]i \text | 在定位行前面插入文本 “text”,支持 \n 换行 |
c | [地址]c \text | 用 “text”替换定位到的所有行(整行替换) |
w | [地址]w /PATH/FILE | 将定位到的行保存到指定文件(覆盖原文件内容) |
r | [地址]r /PATH/FILE | 读取指定文件的内容,追加到定位行后面(实现文件合并) |
= | [地址]= | 为定位到的行打印行号(单独输出在行首) |
! | [地址]!命令 | 条件取反:对 “不满足地址” 的行执行命令(如 /error/!d 表示 “除含 error 的行外都删除”) |
s | [地址]s/原内容/新内容/标记 | 查找替换(核心命令),分隔符可自定义(如 s@@@、s###) |
替换命令(s)的关键标记
替换命令 s/// 是 sed 最常用的功能,通过 “标记” 扩展灵活性,常用标记如下:
- g:全局替换(默认仅替换每行第一个匹配项)
- w /PATH/FILE:将替换成功的行保存到指定文件
- p:显示替换成功的行(需配合 -n)
- i:忽略大小写匹配(如 s/error/INFO/gi 表示全局忽略大小写替换)
此外,替换中可使用特殊符号:
- &:表示匹配到的完整内容(如 s/int/&eger/g 会将 “int” 替换为 “integer”)
- \n(n 为数字):引用正则中 () 捕获的第 n 个分组(如 s/(name):(\w+)/\2=\1/ 会将 “name:Tom” 替换为 “Tom=name”)
sed 高级命令:模式空间与保持空间
sed 内部维护两个缓存区:模式空间(Pattern Space) 和 保持空间(Hold Space)。模式空间用于临时存储当前处理的行,保持空间用于暂存数据,高级命令通过操作这两个空间实现复杂文本处理(如跨行处理、数据暂存)。
命令 | 作用说明 |
---|---|
h | 将模式空间的内容覆盖到保持空间(原保持空间内容被清空) |
H | 将模式空间的内容追加到保持空间(原内容后加换行符) |
g | 将保持空间的内容覆盖到模式空间(原模式空间内容被清空) |
G | 将保持空间的内容追加到模式空间(原内容后加换行符) |
x | 交换模式空间与保持空间的内容 |
n | 读取下一行文本覆盖到模式空间(替换当前行,跳过后续命令) |
N | 读取下一行文本追加到模式空间(形成多行模式空间,可跨行处理) |
d | 删除模式空间中的所有内容(终止当前循环,读取下一行) |
D | 仅删除多行模式空间中的第一行(不终止循环,可继续处理剩余内容) |
提示:高级命令需结合实际场景理解,例如用 N+D 可实现 “删除空行”“合并多行” 等操作。
sed 实战示例:从基础到进阶
以下示例覆盖日常工作中最常用的 sed 场景,所有示例均使用变量(如 $pattern、$path_to_file)表示动态内容,实际使用时需替换为具体值(如 /var/log/nginx.log)。
1. 精准查看指定内容(抑制自动打印)
通过 -n+p 仅显示匹配的行,避免输出冗余内容:
# 显示包含指定模式的行
sed -n "/$pattern/p" $path_to_file
# 显示两个模式之间的所有行
sed -n "/$start_pattern/,/$end_pattern/p" $path_to_file
# 显示指定行
sed -n "${line_num}p" $path_to_file
# 显示行范围
sed -n "$from_line,$to_line)p" $path_to_file
2. 批量删除指定行
删除操作不修改原文件(除非加 -i),仅输出处理后的结果:
# 删除第 N 行
sed "${line_num}d" $path_to_file
# 删除所有包含指定模式的行
sed "/$pattern/d" $path_to_file
# 删除最后一行
sed "$d" $path_to_file
3. 插入与替换行(整行操作)
3.1 在指定行后追加内容
# 在第 N 行后追加文本
sed "${line_num}a\ $content" $path_to_file
# 在包含模式的行后追加文本(支持换行)
sed "/$pattern/a hello\nworld" $path_to_file
3.2 在指定行前插入内容
# 在第 N 行前插入文本
sed "${line_num}i\ $content" $path_to_file
# 在包含模式的行前插入文本
sed "/$pattern/i $content" $path_to_file
3.3 替换指定行(整行替换)
# 用内容替换第 N 行
sed "${line_num}c\ $new_content" $path_to_file
# 用内容替换所有包含模式的行
sed "/$pattern/c\ $new_content" $path_to_file
4. 合并文件:插入外部文件内容
通过 r 命令将外部文件内容插入到指定位置:
# 在每一行后插入外部文件内容
sed "r $external_file" $target_file
# 在第 N 行后插入外部文件内容
sed "${line_num}r $external_file" $target_file
# 在指定行范围后插入外部文件内容
sed "$from_line,$to_line r $external_file" $target_file
5. 保存处理结果到新文件
5.1 保存匹配行到新文件
# 将包含模式的行保存到新文件(原文件不变)
sed -n "/$pattern/w $new_file" $source_file
5.2 直接修改原文件(带备份)
# 直接修改原文件,并备份为 “原文件.bak”
sed -i.bak "s/$old/$new/g" $target_file
6. 查找替换:从基础到高级
6.1 基础替换(全局替换)
# 全局替换文件中所有 “old” 为 “new”
sed "s/$old/$new/g" $target_file
6.2 指定行替换
# 仅在第 N 行替换 “old” 为 “new”
sed "${line_num}s/$old/$new/g" $target_file
# 仅在包含模式的行中替换(忽略大小写)
sed "/$pattern/s/$old/$new/gi" $target_file
6.3 引用匹配内容(& 与分组)
# 用 & 引用匹配的完整内容(给 “link” 后加 “er”)
sed 's/link/&er/g' $file
# 用 \1 引用分组内容(交换 “name:value” 为 “value=name”)
sed 's/\(name\):\(.*\)/\2=\1/g' $file
7. 扩展用法:多点编辑与脚本执行
7.1 一次执行多个命令(多点编辑)
通过 -e 实现 “删除 + 插入” 组合操作:
# 1. 在第 1 行前插入文本;2. 在第 1 行后追加文本
sed -e "1i $insert_content" -e "1a $append_content" $file
7.2 从脚本文件执行命令
当命令较多时,将指令写入脚本文件(如 sed_script.sed):
# sed_script.sed 内容示例
# 1d # 删除第 1 行
# s/error/INFO/g # 全局替换 error 为 INFO
# /EOF/w result.txt # 将包含 EOF 的行保存到 result.txt
# 执行脚本文件
sed -f $sed_script $target_file
8. 配合正则:扩展正则的使用
通过 -r(或 -E)支持扩展正则,无需转义特殊符号:
# 匹配 “error” 或 “warn”(扩展正则的 “|” 无需转义)
sed -r -n "/error|warn/p" $log_file
# 匹配 “num” 后跟 1-3 个数字(扩展正则的 “{n,m}” 无需转义)
sed -r "s/num([0-9]{1,3})/number\1/g" $file
总结
sed 作为 Linux 文本处理的核心工具,其优势在于自动化、高效性和灵活性。掌握 “地址定位 + 命令操作” 的核心逻辑后,可轻松应对批量文本修改、日志过滤、格式转换等场景。
建议从基础命令(s/d/p)和示例入手,熟悉后再探索模式空间与保持空间的高级用法,逐步将 sed 融入日常工作流,提升文本处理效率。