跳转到内容

sed

sed 是一个流编辑器,用于对文本进行转换和处理。它逐行读取输入,在内部缓冲区(模式空间)中进行操作,然后将结果输出。主要功能包括文本替换、删除、插入和筛选等,擅长批量文本处理

Terminal window
sed [选项] 'command' 文件名
  1. 读取输入:sed 从标准输入读取一行数据
  2. 存储在模式空间:读取的行存储在 sed 的内部缓冲区,称为模式空间
  3. 执行命令:sed 对模式空间中的内容执行用户指定的命令
  4. 输出:命令执行完毕后,sed 将模式空间的内容输出到标准输出,然后清空模式空间,准备处理下一行

重复上述操作,直到文件末尾

选项列表

选项 说明
-e 添加执行的 command,可以多次使用多个 -e 来执行多个命令,通常省略也可以
-n 取消默认输出,只有明确用 p 命令时才会打印输出
-i 直接把修改结果写回原文件(危险操作,谨慎使用)
-f script.sed 从指定文件中读取 sed 脚本
--version 查看 sed 版本信息
--help 查看帮助信息

命令列表

命令 功能
s 替换指定字符
p 打印行
d 删除行
a 插入文本到指定行后
i 插入文本到指定行前
c 替换整行内容
q 提前退出
r 读入文件内容并插入原文本
w 将匹配的内容写入文件
{} 多条命令组合
= 显示行号

语法:

Terminal window
's/原内容/新内容/[标记]'

常用标志:

  • g:贪婪匹配,替换每一行中的所有匹配项
  • i:忽略大小写
  • <N>:替换第 <N> 个匹配项

示例:

Terminal window
# 每行替换第一个 old 为 new
sed 's/old/new/' file.txt
# 每行替换所有 old 为 new
sed 's/old/new/g' file.txt
# 每行替换第二个 apple 为 APPLE
sed 's/apple/APPLE/2' file.txt

语法:

命令 说明
<N>c 新内容 将第 N 行替换为“新内容”
<N,M>c 新内容 将第 N 到 M 行合并成一行,替换为“新内容”
/pattern/c 新内容 将匹配正则的行替换为“新内容”

如果插入的内容是多行,用 \ 分割

示例:

Terminal window
# 将第 5 行替换为 content
sed '5c content' file.txt
# 将第 1 到 4 行的文本替换为 content
sed '1,4c content' file.txt
# 将匹配 error 的行替换为 content
sed '/error/c content' file.txt
# 将第 3 行替换为两行内容
sed '3c\
第一行content\
第二行content' file.txt

sed '3c 第一行content\n第二行content' file.txt 这样写是错的,因为 \n 不会被识别为换行,sed 会把整段当作一行插入

通常要搭配 -n 选项使用,否则可能重复打印

语法:

命令 说明
'<N>p' 打印第 N 行
'<N,M>p' 打印第 N-M 行
'/pattern/p' 打印匹配正则的行
'/pattern/!p' 打印不匹配正则的行

示例:

Terminal window
# 打印第 3 行
sed -n '3p' file.txt
# 打印第 2 行到第 4 行
sed -n '2,4p' file.txt
# 打印包含 error 的所有行
sed -n '/error/p' file.txt
# 打印不包含 error 的行
sed -n '/error/!p' file.txt

语法:

命令 说明
'<N>d' 删除第 N 行
'<N,M>d' 删除第 N ~ M 行
'/pattern/d' 删除匹配正则的行

示例:

Terminal window
# 删除第 3 行
sed '3d' file.txt
# 删除第 2 行到第 5 行
sed '2,5d' file.txt
# 删除匹配 error 的行
sed '/error/d' file.txt
# 删除空行
sed '/^$/d' file.txt

语法:

命令 说明
<N>a 内容 在第 N 行后插入一行文本
/pattern/a 内容 在匹配的行后插入文本

如果插入的内容是多行,用 \ 分割 sed 中 a 命令不支持用于多个行地址(如 1,5)

示例:

Terminal window
# 在第 2 行后插入一行文本
sed '2a content' file.txt
# 在每个包含 error 的行下面插入文本
sed '/error/a 插入提示信息' file.txt
# 插入两行文本在第 3 行之后
sed '3a\
第一行 content\
第二行 content' file.txt

语法:

命令 说明
<N>i 内容 在第 N 行前插入一行文本
<N,M>i 内容 在第 N ~ M 行每行前插入内容
/pattern/i 内容 在匹配的行前插入文本

如果插入的内容是多行,用 \ 分割

示例:

Terminal window
# 在第 2 行前插入一行文本
sed '2i content' file.txt
# 在每个包含 server 的行之前插入文本
sed '/server/i 新配置如下' file.txt
# 插入两行文本在第 3 行之前
sed '3i\
第一行 content\
第二行 content' file.txt

sed '2i 第一行content\n第二行content' file.txt 这样写是错的,因为 \n 不会被识别为换行,sed 会把整段当作一行插入

语法:

命令 说明
<N>q 处理到第 N 行后退出
/pattern/q 匹配到正则后退出
'<N,M> {p; q} 区间内打印并提前退出

示例:

Terminal window
# 在第 5 行后退出
sed '5q' file.txt
# 遇到包含 ERROR 的行,立刻退出
sed '/ERROR/q' logfile.txt
# 只输出前 50 行
sed -n '1,100{p;50q}'
# 打印前 5 行
sed -n '1,5p;5q'

该命令用于在指定的行后读取外部文件的内容,并将这些内容插入到输出中。

语法:

语法格式 说明
<N>r 文件名 在第 N 行后插入文件内容
/pattern/r 文件名 在匹配到正则的行后插入文件
<N,M>{/pattern/r 文件名} 在第 N 至 M 行中匹配到 pattern 的行后插入文件内容

示例:

Terminal window
# 将 insert.txt 文件的内容插入到 input.txt 的第 3 行后面
sed '3r insert.txt' input.txt
# 查找所有以 #INSERT_HERE 开头的行,在这些行之后插入 footer.txt 的内容
sed '/^#INSERT_HERE/r footer.txt' main.txt
# 打印前 5 行,并在第 5 行后插入文件内容
sed -n '1,5p;5r insert.txt' file.txt
# 第 1 至 10 行中匹配到 pattern 的行后插入文件内容
sed '1,10{/pattern/r file.txt}' input.txt

该命令用于将匹配的行内容写入指定的文件中,同时也会将原行输出到标准输出(除非使用 -n 取消默认输出)。

语法:

语法 说明
<N>w 文件名 将第 N 行写入指定文件
<N,M>w 文件名 指定行范围写入文件
/pattern/w 文件名 将匹配正则的行写入文件

示例:

Terminal window
# 把第 5 行写入文件
sed '5w out.txt' input.txt
# 把第 5 到 6 行写入文件
sed '5,6w out.txt' input.txt
# 所有包含 ERROR 的行都会被写到 error.log
sed '/ERROR/w error.log' server.log
# WARN 行写入 warn.log,ERROR 行写入 error.log
sed '/WARN/w warn.log; /ERROR/w error.log' log.txt

{} 用于把多条 sed 命令组合在一起,针对同一个地址或模式范围一起执行。大括号内命令之间用分号 ; 或换行分隔。

语法:

Terminal window
'地址{command1; command2; ...; commandN}'
  • 地址:可以是行号、地址范围(N,M)、模式匹配(/pattern/)等
  • command1..N:大括号里的一条或多条 sed 命令

示例:

Terminal window
# 对第 2~4 行执行:替换 foo 为 bar,然后打印
sed -n '2,4{ s/foo/bar/; p }' file.txt
# 匹配含 ERROR 的行:写入 error.log,然后删除
sed '/ERROR/{ w error.log; d }' app.log
# 在第 1-3 行替换内容并打印、删除(换行写法,推荐)
sed '1,3{
s/foo/bar
p
d
}' file.txt
命令 说明
sed '=' file.txt 显示每一行的行号
sed -n '10{=;p}' 显示第 10 行的行号和内容
sed -n '/main/{=;p}' 显示包含 “main” 的行号和内容
sed '=' file.txt | paste - - 将行号和内容合并在一行显示(推荐)

进行原地替换时,例如 sed s/REGEX/SUBSTITUTION/ input.txt > input.txt 并不是安全的做法。当使用 > 重定向输出时,shell 会先打开目标文件并将其截断(清空内容),然后才执行 sed 命令。这意味着 sed 试图读取的是已经被清空的文件,最终导致原文件内容丢失。

这不是 sed 特有的行为,而是 shell 重定向机制导致的。任何使用 command input > input 形式的命令(如 awk、grep 等)都会遇到同样的问题,因为文件截断发生在命令执行之前。