[toc]

sed概述

sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。
sed也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于Shell脚本中,用以完成各种自动化处理任务。

sed工作流程

sed 的工作流程主要包括读取、执行和显示三个过程。

读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。
————————————————

示例

  1. sed先是按行读取文件内容
  2. 每读取一行内容,都会进行一次判断,是不是你想要的行
    • 如果是,你想要的那一行(第三行)则判断执行的后续动作(p d s a i c)
    • 如果不是,继续判断是否加了-n选项
      • 如果加了-n,就读取下一行
      • 如果没加-n,就会将所有内容输出到命令行(始终执行一次默认输出)
  3. 动作处理完成后,输出指定的内容
  4. 即便是读取完了,内容也输出了,sed也会继续往后读,直到文件的最后一行

sed语法

sed命令选项 选项含义
-n 取消默认输出
-r 支持扩展正则

sed - 查

sed - 语法动作

1
2
3
4
5
6
# 语法结构
sed 'np' [文件]

# 动作
p(print) # 打印
r # 支持正 则

示例

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# sed显示单行内容
sed '3p' zls.txt
1,zls,666
2,wls,777
3,cls,888
3,cls,888
4,lls,999

# sed取消默认输出
sed -n '3p' zls.txt
3,cls,888

# sed显示多行内容并取消默认输出 '1,3p'就是1到3行!!!
sed -n '1,3p' zls.txt
1,zls,666
2,wls,777
3,cls,888

# sed模糊查询
sed -n '/zls/p' zls.txt
1,zls,666
sed -nr '/zls|cls/p' zls.txt
1,zls,666
3,cls,888
sed -n '/zls/,/cls/p' zls.txt
1,zls,666
2,wls,777
3,cls,888

# sed实现 grep -A
sed -n '/zls/,+2p' zls.txt
1,zls,666
2,wls,777
3,cls,888
grep 'zls' -A 2 zls.txt
1,zls,666
2,wls,777
3,cls,888

# sed 隔指定行数读取一行
sed -n '1~2p' zls.txt
1,zls,666
3,cls,888
sed -n '1~3p' zls.txt
1,zls,666
4,lls,999

sed - 删

sed - 语法动作

1
2
3
4
5
6
# 语法结构
sed -i.bak 'nd' [文件]

# 动作
-i # 备份并指定备份文件名后缀
d(delete) # 删除

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 备份并删除
sed -i.bak '$d' zls.txt
## 加"-i"进行备份;加"-n"会把所有文件内容都删除

# 删除指定行数,不修改原文件
sed '2d' zls.txt

# 删除最后一行
sed '$d' zls.txt
1,zls,666
3,cls,888

# 包含zls的行到cls的行都删掉
sed -n '/zls/,/cls/d' zls.txt

sed - 增

sed - 语法动作

1
2
3
4
5
6
7
8
# 语法结构
sed -i.bak 'nd' [文件]

# 动作
-i # 备份并指定备份文件名后缀
c(replace) # 替换整行内容
a(append) # 追加
i(insert) # 插入

示例

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 备份并修改
sed -i.bak '$a5,huanglong,438' zls.txt
## 如果没有指定行,所有内容都会执行动作;语法结尾可以输入多个文件

# 替换整行内容
cat zls.txt
1,zls,666
3,cls,888
4,lls,999
sed '2c2,huanglong,438' zls.txt
1,zls,666
2,huanglong,438
4,lls,999

# 追加
sed '$a5,huanglong,438' zls.txt
1,zls,666
3,cls,888
4,lls,999
5,huanglong,438
sed '2a5,huanglong,438' zls.txt
1,zls,666
3,cls,888
5,huanglong,438
4,lls,999
sed '1a2,huanglong,438' zls.txt
1,zls,666
2,huanglong,438
3,cls,888
4,lls,999

# 插入
sed '$i2,huanglong,438' zls.txt
1,zls,666
3,cls,888
2,huanglong,438
4,lls,999
sed '1i2,huanglong,438' zls.txt
2,huanglong,438
1,zls,666
3,cls,888
4,lls,999

sed - 改

sed - 语法动作

1
2
3
4
5
6
7
# 语法结构
sed 's#xxx#yyy#g' [文件]
sed 's@xxx@yyy@g' [文件]

# 动作
s(substitute) # 替换
g(global) # 全局

示例

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
# 基础用法
sed 's#zls#ZLS#g' zls.txt
1,ZLS,666
2,wls,777
3,cls,888
4,lls,999

# 使用正则
sed 's#[0-9]#666#g' zls.txt
666,zls,666666666
666,wls,666666666
666,cls,666666666
666,lls,666666666

# 后向引用
ifconfig eth0|sed -nr 's#^.*inet (.*) net.*#\1#gp'
10.0.0.61
ip a s eth1|sed -nr 's#^.*inet (.*)/24.*#\1#gp'
172.16.1.61

## 后向应用所有的括号前都需要加'\'进行转译
172.16.1.52(172.16.1.52:3306) (current master)

sed -nr 's#(.*)\(.*\) \(current master\)$#\1#gp'
sed -nr 's#(.*)\((.*)\) \(current master\)$#\2#gp'

sed的模式空间

sed - 语法动作

1
2
3
4
5
# 语法结构
sed 'N;s#xxx#yyy#g' [文件]

# 动作
N # 在读取文件时,让sed把下一行内容一起读进去

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# sed每一次读取文件带一行,会把\n也读入进去
sed 'N;s#\n# #g' zls.txt
1,zls,666 2,dsa,23
3,cls,888 4,lls,999
5,dsa,564 6,sda,333
7

# n行减1N
sed 'N;N;N;N;N;N;s#\n# #g' zls.txt
1,zls,666 2,dsa,23 3,cls,888 4,lls,999 5,dsa,564 6,sda,333 7

# 拓展sed中循环
do done
sed ':label;N;s#\n# #g;t label' zls.txt
1,zls,666 2,dsa,23 3,cls,888 4,lls,999 5,dsa,564 6,sda,333 7

# 图
for do done
:label
N;s#\n# #g
t label