前言
在本系列上一篇 【】,我们介绍了 Linux 三剑客中的 grep
命令用法。而实际上,在三剑客中,grep
只能算是小弟,它的作用更多只是通过正则表达式的加持,实现针对文本的模式查询。
而三剑客中,真正重量级的命令是 sed
和 awk
, sed
其实是 stream editor(流编辑器)
的缩写,因此,sed 命令它其实是能够起到文本编辑器的作用。本篇我们就来介绍这个 伪装成Linux命令的编辑器 sed
sed 命令概述
sed
命令的语法如下:
1
|
sed -命令参数 '操作指令' 文本文件或管道输入
|
sed
是一个行编辑器,这里的操作指令会按行来对文本进行处理
命令参数
它的命令参数主要有如下一些:
命令参数 |
含义 |
-n |
关闭默认输出 |
-r |
支持正则表达式扩展 |
-i |
直接对源文件进行操作 |
-e |
指定操作指令(默认开启,可指定多个) |
-f |
从文件读取操作指令 |
默认输出
1
2
|
sed '/root/p' /etc/passwd
# 其实会显示passwd文件中所有行,其中包含root用户的行重复显示
|
1
2
|
sed -n '/root/p' /etc/passwd
# 加上-n参数,才会关闭sed本身的默认输出,这样才是通过p指令显示匹配的行
|
修改原文件
实际工作中,-i
参数是一个比较危险的参数,因为这个参数会直接修改原文件
1
2
3
|
sed -i '/root/q' /etc/passwd
# 这个操作会导致passwd文件中只包含有root用户这一行,因为指令q会在匹配到行后直接退出
# 而sed这时的输出内容会直接写入原文件
|
比较安全的做法,可以在使用-i
参数时指定一个备份文件, 也就是在 -i
后指定一个备份文件的后缀名
1
2
|
sed -i.bak '/root/q' /etc/passwd
# 这个操作虽然还是会修改passwd文件,但在修改前会备份一个.bak文件,便于恢复
|
多重指令
sed
命令的指令可以有多个,但又多个指令时,需要为每个指令指定一个-e
参数,如果只使用 1 个指令,则这个 -e
可以忽略
1
2
|
sed -e '=' -e '/root/q' /etc/passwd
# = 指令会输出当前处理行的行号
|
如果我们想重复指定 -e
,也可以通过 ;
组合指令
1
2
|
sed '=;/root/q' /etc/passwd
# 和通过 -e 多重指定效果一样
|
操作指令说明
在上面的参数介绍中,我们其实已经使用了 如 p
, q
等指令。
而这个操作指令,其实是由两部分组成,也就是寻址部分和操作部分:
- 寻址:
sed
命令是行处理命令,寻址其实就是指定要处理的行
- 操作: 针对匹配寻址规则的行要执行的操作
寻址规则
寻址格式 |
含义 |
数字 |
指定行号匹配 |
m~n |
从m行开始,按步长n匹配 |
$ |
匹配末行 |
/regex/ |
按正则匹配 |
m,n |
从m行开始,匹配到n行 |
m,+n |
从m行开始,再匹配n行 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
sed -n '5p' /etc/passwd
# 显示第 5 行内容
sed -n '2~3p' /etc/passwd
# 显示从第2行开始,步长3递进,即第 2,5,8,11,14.... 行内容
sed -n '$p' /etc/passwd
# 显示最后一行内容
sed -n '/qiucao/p' /etc/passwd
# 显示包含qiucao的行内容
sed -n '5,8p' /etc/passwd
# 显示第 5 行到第 8 行内容
sed -n '5,+5p' /etc/passwd
# 显示第 5,6,7,8,9,10行内容
|
操作指令
操作指令 |
含义 |
p |
打印匹配行 |
= |
输出匹配行行号 |
l |
打印匹配行并显示不可见字符 |
s |
正则表达式匹配和替换 |
c |
匹配行整行替换 |
a |
在匹配行后追加内容 |
i |
在匹配行前追加内容 |
d |
删除匹配行 |
r |
在匹配换行后追加内容(从文件中) |
w |
将匹配行内容写入文件 |
q |
匹配后退出,不再继续匹配 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
sed -n '=;5p' /etc/passwd
# 显示所有行号并打印第 5 行内容
sed -n '=;5l' /etc/passwd
# 和上条命令类似,但行末的结束符($)也会打印出来
sed -r '=;s/^m\w*/test/g' /etc/passwd
# 替换所有以m开头的用户名为test, 加/g的作用是在行内替换所有匹配字符,否则只替换第一个
sed '=;5c\测试一下' /etc/passwd
# 将第5行替换为 “测试一下”
sed '=;5a\测试一下' /etc/passwd
# 在第5行内容后追加一行
sed '=;5i\测试一下' /etc/passwd
# 在第5行内容前插入一行
sed '=;5d' /etc/passwd
# 删除第5行
sed '=;5r test.txt' /etc/passwd
# 从test.txt中读取一行并添加到第5行后
sed '=;5w test.txt' /etc/passwd
# 将第5行内容写入到test.txt
|
模式空间和保留空间
上面介绍的操作指令,主要是针对行内操作的一些指令。 我们既然说 sed
其实是一个编辑器,那么对于多行的文本编辑操作,比如整行的复制、粘贴、剪切等,当然也是支持的。
这就要说到 sed
命令处理时,预留的两个内存空间了:
- 模式空间: 存储当前处理行的内容,每完成一行的处理,处理完的内容放到这个空间中
- 保留空间: 用于临时存储数据,可以认为是像剪切板一样的一个缓存空间,用于不同行内容的交换。初始默认只有一个
\n
回车符
操作指令 |
用法 |
h |
将模式空间内容复制到保留空间,替换原内容(\n) |
H |
追加模式空间内容到保留空间 |
g |
保留空间内容复制到模式空间,覆盖原内容 |
G |
保留空间内容追加到模式空间原内容后 |
x |
交换模式空间和保留空间内容 |
n |
立即读取下一行,并复制到模式空间 |
N |
立即读取下一行,并追加到当前模式空间(常用于行合并) |
示例
1
2
3
4
5
|
sed '=;2h;3H;5x;8G' /etc/passwd
# 2h复制第2行到保留空间
# 3H复制第3行并追加到现有保留空间后
# 5x将当前模式空间和保留空间进行交换,复制的内容替换了原第 5 行的内容
# 8G将保留空间内容(原第5行模式空间内容)追加到当前模式空间即第8行内容后
|

常用 sed 实操案例
1. 删除空白行
1
2
|
sed -i '/^\s*$/d' test.txt
# 正则匹配仅包含空白字符的行并删除
|
2. 给文件添加行号
1
2
3
|
sed '=' test.txt | sed 'N;s/\n/\t/'
# 先用sed命令获取行号,或加到每行默认输出前一行
# 通过管道传递到后一个sed命令,通过 N 指令合并两行,并将 回车符替换为制表符
|
3. 提取所有图片链接
1
2
|
sed -nr 's/.*src="(.*\.png).*/\1/p' source.html
# 正则表达式匹配图片链接,利用正则表达式分组保存路径并替换原有整行内容
|
4. 提取log中异常行
1
2
|
sed -n '/ERROR/{=;p}' app.log
# 匹配日志中包含ERROR字样的行并打印输出行号
|
结语
以上就是关于 linux 三剑客之 sed
命令的系统梳理,后续还会继续带来 awk
命令的总结! 更多测试扩展技能,欢迎关注秋草的体系化提升课程,回复 大纲
获取详细目录。