Featured image of post Linux文本处理三剑客 Sed

Linux文本处理三剑客 Sed

本篇带来Linux三剑客中的sed命令,伪装成命令的编辑器

前言

在本系列上一篇 【】,我们介绍了 Linux 三剑客中的 grep 命令用法。而实际上,在三剑客中,grep 只能算是小弟,它的作用更多只是通过正则表达式的加持,实现针对文本的模式查询。 而三剑客中,真正重量级的命令是 sedawk, 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 命令的总结! 更多测试扩展技能,欢迎关注秋草的体系化提升课程,回复 大纲 获取详细目录。

使用 Hugo 构建
主题 StackJimmy 设计