sed
sed 是一个流编辑器,用于对文本进行转换和处理。它逐行读取输入,在内部缓冲区(模式空间)中进行操作,然后将结果输出。主要功能包括文本替换、删除、插入和筛选等,擅长批量文本处理
sed [选项] 'command' 文件名- 读取输入:sed 从标准输入读取一行数据
- 存储在模式空间:读取的行存储在 sed 的内部缓冲区,称为模式空间
- 执行命令:sed 对模式空间中的内容执行用户指定的命令
- 输出:命令执行完毕后,sed 将模式空间的内容输出到标准输出,然后清空模式空间,准备处理下一行
重复上述操作,直到文件末尾
选项列表
| 选项 | 说明 |
|---|---|
-e |
添加执行的 command,可以多次使用多个 -e 来执行多个命令,通常省略也可以 |
-n |
取消默认输出,只有明确用 p 命令时才会打印输出 |
-i |
直接把修改结果写回原文件(危险操作,谨慎使用) |
-f script.sed |
从指定文件中读取 sed 脚本 |
--version |
查看 sed 版本信息 |
--help |
查看帮助信息 |
命令列表
| 命令 | 功能 |
|---|---|
s |
替换指定字符 |
p |
打印行 |
d |
删除行 |
a |
插入文本到指定行后 |
i |
插入文本到指定行前 |
c |
替换整行内容 |
q |
提前退出 |
r |
读入文件内容并插入原文本 |
w |
将匹配的内容写入文件 |
{} |
多条命令组合 |
= |
显示行号 |
s:字符串替换
Section titled “s:字符串替换”语法:
's/原内容/新内容/[标记]'常用标志:
g:贪婪匹配,替换每一行中的所有匹配项i:忽略大小写<N>:替换第<N>个匹配项
示例:
# 每行替换第一个 old 为 newsed 's/old/new/' file.txt# 每行替换所有 old 为 newsed 's/old/new/g' file.txt# 每行替换第二个 apple 为 APPLEsed 's/apple/APPLE/2' file.txtc:整行替换
Section titled “c:整行替换”语法:
| 命令 | 说明 |
|---|---|
<N>c 新内容 |
将第 N 行替换为“新内容” |
<N,M>c 新内容 |
将第 N 到 M 行合并成一行,替换为“新内容” |
/pattern/c 新内容 |
将匹配正则的行替换为“新内容” |
如果插入的内容是多行,用
\分割
示例:
# 将第 5 行替换为 contentsed '5c content' file.txt# 将第 1 到 4 行的文本替换为 contentsed '1,4c content' file.txt# 将匹配 error 的行替换为 contentsed '/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' |
打印不匹配正则的行 |
示例:
# 打印第 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' |
删除匹配正则的行 |
示例:
# 删除第 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)
示例:
# 在第 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 内容 |
在匹配的行前插入文本 |
如果插入的内容是多行,用
\分割
示例:
# 在第 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} |
区间内打印并提前退出 |
示例:
# 在第 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 的行后插入文件内容 |
示例:
# 将 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 文件名 |
将匹配正则的行写入文件 |
示例:
# 把第 5 行写入文件sed '5w out.txt' input.txt# 把第 5 到 6 行写入文件sed '5,6w out.txt' input.txt# 所有包含 ERROR 的行都会被写到 error.logsed '/ERROR/w error.log' server.log# WARN 行写入 warn.log,ERROR 行写入 error.logsed '/WARN/w warn.log; /ERROR/w error.log' log.txt{}:命令块
Section titled “{}:命令块”{} 用于把多条 sed 命令组合在一起,针对同一个地址或模式范围一起执行。大括号内命令之间用分号 ; 或换行分隔。
语法:
'地址{command1; command2; ...; commandN}'- 地址:可以是行号、地址范围(
N,M)、模式匹配(/pattern/)等 command1..N:大括号里的一条或多条 sed 命令
示例:
# 对第 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 等)都会遇到同样的问题,因为文件截断发生在命令执行之前。
man sed- GNU sed Manual