0%

sed命令

sed 命令详解:流编辑器的文本处理艺术

sed(Stream Editor,流编辑器)是 Linux 中处理文本的核心工具之一,它以逐行处理的方式对数据流进行编辑(如替换、删除、新增等),且默认不修改原文件,仅输出处理结果。掌握 sed 能高效完成批量文本修改、日志分析、配置文件处理等任务。

sed 工作原理与基本语法

工作流程

  1. 读取:从输入流(文件或管道)中读取一行数据到缓冲区(称为 “模式空间”)。
  2. 处理:根据提供的 sed 命令(规则)处理缓冲区中的行。
  3. 输出:将处理后的行输出到标准输出(屏幕)。
  4. 重复:直到所有行处理完毕。

特点:默认不修改原文件,仅输出处理结果;可通过 -i 选项直接修改原文件。

基本语法

1
sed [选项] '地址范围 动作' 输入文件
核心选项
选项 功能说明
-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
# 打印第2行(-n 配合 p 仅输出指定行)
sed -n '2p' file.txt

# 删除第3到5行
sed '3,5d' file.txt

# 从第4行到结尾,每行后追加"---"
sed '4,$a ---' file.txt

正则表达式寻址

/正则表达式/ 匹配行,仅处理符合条件的行。

  • 格式:/pattern/动作(如 /error/d 表示删除包含 error 的行)。
  • 扩展正则需加 -r 选项(如 /^[0-9]+/p 匹配以数字开头的行)。

示例

1
2
3
4
5
6
7
8
# 打印包含 "error" 的行(日志分析常用)
sed -n '/error/p' app.log

# 删除以 "#" 开头的注释行(不包括空行)
sed '/^#/d' config.ini

# 替换以 "name:" 开头的行中的 "old" 为 "new"
sed -r '/^name:/s/old/new/' data.txt

混合寻址

结合行号和正则,实现更精确的范围选择。

1
2
3
4
5
# 从第5行开始,到包含 "end" 的行结束,删除这些行
sed '5,/end/d' file.txt

# 从包含 "start" 的行到第10行,每行前插入 "==="
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
# 将每行第一个 "apple" 替换为 "banana"
sed 's/apple/banana/' fruit.txt

# 全局替换所有 "cat" 为 "dog"
sed 's/cat/dog/g' pets.txt

# 替换第2个 "error" 为 "warning",并打印修改的行
sed -n 's/error/warning/2p' app.log

# 忽略大小写替换 "hello" 为 "HELLO"
sed 's/hello/HELLO/i' greet.txt

删除行(d 动作)

用于删除指定行,注意 d 后无其他内容。

1
2
3
4
5
6
7
8
# 删除空行(正则 ^$ 匹配空行)
sed '/^$/d' file.txt

# 删除所有包含 "temp" 的行
sed '/temp/d' list.txt

# 保留第2到5行,删除其他行(反向思维:先删除所有行,再恢复指定行)
sed '1d;6,$d' file.txt # 分号分隔多个命令

新增与替换行(a/i/c 动作)

  • a:在指定行后追加;i:在指定行前插入;c:替换整行。

示例

1
2
3
4
5
6
7
8
# 在第3行后追加 "new line"
sed '3a new line' file.txt

# 在包含 "title" 的行前插入两行文本(多行用 \ 分隔)
sed '/title/i line1\nline2' file.txt # 或用 \ 换行:i line1\ line2

# 用 "replaced" 替换所有以 "old" 开头的行
sed '/^old/c replaced' file.txt

写入文件(w 动作)

将指定行写入其他文件(可用于提取特定内容)。

1
2
3
4
5
# 将第1到5行写入 output.txt
sed '1,5w output.txt' input.txt

# 将包含 "success" 的行写入 success.log
sed -n '/success/w success.log' app.log # -n 避免重复输出

高级用法:多命令、原地修改与脚本

多命令执行

  • -e 选项分隔多个命令,或用分号 ; 连接。
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
# 备份原文件(加 .bak 后缀),再修改
sed -i.bak 's/old/new/g' file.txt # 修改后生成 file.txt.bak

# 直接修改原文件(无备份,危险!)
sed -i 's/error/warn/g' app.log

从脚本文件读取命令(-f 选项)

复杂的 sed 操作可写入脚本文件,提高可读性。

1
2
3
4
5
6
7
# 脚本文件:sed_commands.sed
s/hello/hi/g
/^test/d
3a --- END ---

# 执行脚本
sed -f sed_commands.sed input.txt

实战案例

1. 批量修改文件名

1
2
3
# 将当前目录下所有 .txt 文件名中的 "old" 改为 "new"
ls *.txt | sed -n 's/old/new/p' | xargs -I {} mv {old} {new}
# 解析:sed 生成新文件名,xargs 执行 mv 命令

2. 清理 Nginx 日志(保留关键信息)

1
2
3
# 提取日志中的 IP、时间、请求路径(假设日志格式:IP 时间 "请求" ...)
sed -r 's/^([0-9.]+) .* \[(.*)\] ".* (\/.*?) .*/\1 \2 \3/' access.log
# 解析:用正则分组提取 IP(\1)、时间(\2)、路径(\3)

3. 配置文件批量替换

1
2
# 将所有 .conf 文件中的 "port 80" 改为 "port 8080",并备份
find . -name "*.conf" -exec sed -i.bak 's/port 80/port 8080/g' {} \;

注意事项

  1. 正则转义:基础 sed 中某些元字符(如 +?)需用 \ 转义,加 -r 选项可避免。
  2. 特殊字符处理:替换包含 / 的字符串时,可改用其他分隔符(如 s#/old#/new#g)。
  3. 原文件保护:使用 -i 前建议先备份(如 -i.bak),或先不加 -i 测试输出是否正确。
  4. 空行与空格:正则 ^$ 匹配空行,^[[:space:]]*$ 匹配空行或仅含空格的行。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10