sed 命令详解:流编辑器的文本处理艺术
sed(Stream Editor,流编辑器)是 Linux 中处理文本的核心工具之一,它以逐行处理的方式对数据流进行编辑(如替换、删除、新增等),且默认不修改原文件,仅输出处理结果。掌握 sed 能高效完成批量文本修改、日志分析、配置文件处理等任务。
sed 工作原理与基本语法
工作流程
- 读取:从输入流(文件或管道)中读取一行数据到缓冲区(称为 “模式空间”)。
- 处理:根据提供的
sed 命令(规则)处理缓冲区中的行。
- 输出:将处理后的行输出到标准输出(屏幕)。
- 重复:直到所有行处理完毕。
特点:默认不修改原文件,仅输出处理结果;可通过 -i 选项直接修改原文件。
基本语法
核心选项
| 选项 |
功能说明 |
-n |
静默模式,仅输出被 p 动作指定的行(抑制默认输出)。 |
-e |
允许在同一行指定多个 sed 命令(多命令执行)。 |
-f 脚本文件 |
从文件中读取 sed 命令(适合复杂脚本)。 |
-r |
启用扩展正则表达式(无需转义 +、? 等元字符)。 |
-i |
直接修改原文件(危险操作,建议先备份或测试)。 |
常用动作
| 动作 |
功能说明 |
a \文本 |
在指定行后追加文本(多行需用 \ 分隔)。 |
i \文本 |
在指定行前插入文本(多行需用 \ 分隔)。 |
c \文本 |
用指定文本替换整行(多行需用 \ 分隔)。 |
d |
删除指定行。 |
p |
打印指定行(常与 -n 配合使用)。 |
s/旧字符串/新字符串/修饰符 |
替换字符(核心动作,详见下文)。 |
w 文件名 |
将指定行写入文件。 |
地址范围:指定要处理的行
sed 通过 “地址范围” 指定对哪些行执行动作,默认对所有行生效。地址可以是行号、正则表达式或两者结合。
行号寻址
- 单一行:
数字(如 3 表示第 3 行)。
- 行范围:
起始行,结束行(如 2,5 表示第 2 到 5 行)。
- 从行号到结尾:
数字,$( 表示第 3 行到最后一行)。
示例:
1 2 3 4 5 6 7 8
| sed -n '2p' file.txt
sed '3,5d' file.txt
sed '4,$a ---' file.txt
|
正则表达式寻址
用 /正则表达式/ 匹配行,仅处理符合条件的行。
- 格式:
/pattern/动作(如 /error/d 表示删除包含 error 的行)。
- 扩展正则需加
-r 选项(如 /^[0-9]+/p 匹配以数字开头的行)。
示例:
1 2 3 4 5 6 7 8
| sed -n '/error/p' app.log
sed '/^#/d' config.ini
sed -r '/^name:/s/old/new/' data.txt
|
混合寻址
结合行号和正则,实现更精确的范围选择。
1 2 3 4 5
| sed '5,/end/d' file.txt
sed '/start/,10i ===' file.txt
|
核心动作详解:替换、删除、新增
字符替换(s 动作)
sed 最常用的功能,格式:s/旧字符串/新字符串/修饰符。
修饰符
g:全局替换(默认仅替换每行第一个匹配项)。
n:替换第 n 个匹配项(如 s/old/new/2 替换每行第二个 old)。
p:替换后打印该行(常与 -n 配合,输出被修改的行)。
i:忽略大小写(如 s/hello/HELLO/i 不区分大小写替换)。
示例:
1 2 3 4 5 6 7 8 9 10 11
| sed 's/apple/banana/' fruit.txt
sed 's/cat/dog/g' pets.txt
sed -n 's/error/warning/2p' app.log
sed 's/hello/HELLO/i' greet.txt
|
删除行(d 动作)
用于删除指定行,注意 d 后无其他内容。
1 2 3 4 5 6 7 8
| sed '/^$/d' file.txt
sed '/temp/d' list.txt
sed '1d;6,$d' file.txt
|
新增与替换行(a/i/c 动作)
a:在指定行后追加;i:在指定行前插入;c:替换整行。
示例:
1 2 3 4 5 6 7 8
| sed '3a new line' file.txt
sed '/title/i line1\nline2' file.txt
sed '/^old/c replaced' file.txt
|
写入文件(w 动作)
将指定行写入其他文件(可用于提取特定内容)。
1 2 3 4 5
| sed '1,5w output.txt' input.txt
sed -n '/success/w success.log' app.log
|
高级用法:多命令、原地修改与脚本
多命令执行
1 2 3 4 5
| sed -e '/^$/d' -e '/^#/d' config.ini
sed '/^$/d;/^#/d' config.ini
|
原地修改文件(-i 选项)
-i 选项让 sed 直接修改原文件(务必谨慎使用,建议先备份)。
1 2 3 4 5
| sed -i.bak 's/old/new/g' file.txt
sed -i 's/error/warn/g' app.log
|
从脚本文件读取命令(-f 选项)
复杂的 sed 操作可写入脚本文件,提高可读性。
1 2 3 4 5 6 7
| s/hello/hi/g /^test/d 3a --- END ---
sed -f sed_commands.sed input.txt
|
实战案例
1. 批量修改文件名
1 2 3
| ls *.txt | sed -n 's/old/new/p' | xargs -I {} mv {old} {new}
|
2. 清理 Nginx 日志(保留关键信息)
1 2 3
| sed -r 's/^([0-9.]+) .* \[(.*)\] ".* (\/.*?) .*/\1 \2 \3/' access.log
|
3. 配置文件批量替换
1 2
| find . -name "*.conf" -exec sed -i.bak 's/port 80/port 8080/g' {} \;
|
注意事项
- 正则转义:基础
sed 中某些元字符(如 +、?)需用 \ 转义,加 -r 选项可避免。
- 特殊字符处理:替换包含
/ 的字符串时,可改用其他分隔符(如 s#/old#/new#g)。
- 原文件保护:使用
-i 前建议先备份(如 -i.bak),或先不加 -i 测试输出是否正确。
- 空行与空格:正则
^$ 匹配空行,^[[:space:]]*$ 匹配空行或仅含空格的行。
v1.3.10