一、sed介绍 🐳

sed (Stream Editor)是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

二、sed 的选项、命令、替换标记 🐟

命令格式:

1
2
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)

1、选项

1
2
3
4
5
6
7
8
-e<script> 或 --expression=<script>:以选项中的指定的script来处理输入的文本文件;
-f<script文件> 或 --file=<script文件>:以选项中指定的script文件来处理输入的文本文件;
-h 或 --help:显示帮助;
-n 或 --quiet或——silent:抑制自动输出,仅显示script处理后的结果;
-V 或 --version:显示版本信息。
-i : 编辑文件内容
-i.bak : 修改时同时创建.bak备份文件。
-r : 使用扩展的正则表达式

2、命令

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
a\ : 在当前行下面插入文本。
i\ : 在当前行上面插入文本。
c\ : 把选定的行改为新的文本。
d : 删除,删除选择的行。
D : 删除模板块的第一行。
s : 替换指定字符
h : 拷贝模板块的内容到内存中的缓冲区。
H : 追加模板块的内容到内存中的缓冲区。
g : 获得内存缓冲区的内容,并替代当前模板块中的文本。
G : 获得内存缓冲区的内容,并追加到当前模板块文本的后面。
l : 列表不能打印字符的清单。
n : 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
N : 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
p : 打印模板块的行。
P : (大写) 打印模板块的第一行。
q : 退出Sed。
b lable : 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
r file : 从file中读行。
t label : if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T label : 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
w file : 写并追加模板块到file末尾。
W file : 写并追加模板块的第一行到file末尾。
! : 表示后面的命令对所有没有被选定的行发生作用。
= : 打印当前行号码。
#: 把注释扩展到下一个换行符以前。

3、替换标记

1
2
3
4
5
6
7
g : 表示行内全面替换。  
p : 表示打印行。
w : 表示把行写入一个文件。
x : 表示互换模板块中的文本和缓冲区中的文本。
y : 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
\1 : 子串匹配标记
& : 已匹配字符串标记

三、sed 用法实例 🐠

1、基础用法

演示实例文档

1
2
3
4
cat aaa
I love php
I love F5
I 666

1、参数p

打印匹配的每一行,一般与选项 -n 连用。

1
2
3
4
5
6
7
sed 'p' aaa
I love php
I love php
I love F5
I love F5
I 666
I 666

2、选项-n

抑制自动输出,仅显示script处理后的结果。

1
2
3
4
sed -n 'p' aaa
I love php
I love F5
I 666

3、选项-e

将脚本中指定的命令添加到处理输入时执行的命令中

多条件,一行中要有多个操作

1
2
3
sed -n -e '/666/p' -e '/php/p' aaa
I love php
I 666

4、选项-f

将文件中指定的命令添加到处理输入时执行的命令中

1
2
3
4
5
cat sed.txt
/php/p

sed -n -f sed.txt aaa
I love php

5、选项-r

使用扩展的正则表达式

1
2
3
sed -n -r '/php|666/p' aaa
I love php
I 666

6、参数 s g

s: 查找替换字符串,通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g

g: 表示用新文本替换现有文本的全部实例

1
2
3
4
sed 's/php/PHP/g' aaa
I love PHP
I love F5
I 666

7、选项-i

编辑文件内容,此选项会直接修改源文件

1
2
3
4
5
6
sed -i 's/php/PHP/g' aaa

cat aaa
I love PHP
I love F5
I 666

8、参数=

显示匹配内容的行号

1
2
3
sed -n '/root/=' passwd
1
10

2、命令匹配模式

匹配模式 含义
10command 匹配第十行
10,20command 匹配从第10行开始,匹配至20行结束
10,+5command 匹配从第10行开始,匹配至15行结束
/pattern1/command 匹配pattern1的行 , 支持正则表达式
/pattern1/,/pattern2/command 匹配到从pattern1开始,匹配到pattern2结束
10,/pattern/command 匹配从第10行开始,匹配到pattern1的行结束
/pattern1/,10command 匹配到pattern1的行开始,到第10行结束匹配

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 匹配第一行
sed -n '1p' aaa
I love PHP

# 匹配第一行到第二行
sed -n '1,2p' aaa
I love PHP
I love F5

# 匹配指定行
sed -n '/PHP/p' aaa
I love PHP

# 匹配指定行到后1行
sed -n '/PHP/,1p' aaa
I love PHP

# 匹配到从PHP开始,匹配到F5结束
sed -n '/PHP/,/F5/p' aaa
I love PHP
I love F5

3、编辑选项

编辑选项 含义
a 行后追加
i 行前追加
r 外部文件读入,行后追加
w 匹配行写入外部文件
d 删除
s/old/new 将行内的第一个old替换为new
s/old/new/g 将行内的全部的old替换为new
s/old/new/2g 将行内从第两个开始,old替换为new
s/old/new/ig 将行内的全部的old替换为new,忽略大小写

(1) 删除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 删除第一行
sed -i '1d' passwd

# 删除第1至3行
sed -i '1,3d' passwd

# 删除包含/sbin/nologin的行
sed -i '/\/sbin\/nologin/d' passwd

# 删除mail到ftp之间的行
sed -i '/mail/,/ftp/d' passwd

# 删除文件的第2行到末尾所有行:
sed '2,$d' passwd

# 删除文件最后一行:
sed '$d' passwd

(2) 增加:

1
2
3
4
5
6
7
8
9
10
11
# 匹配内容 /bin/bash ,在其下一行添加 good 字段
sed -i '/\/bin\/bash/a good' passwd

# 匹配内容以 chrony 开头到以 nginx 开头之间的行,在其上一行添加 good 字段
sed -i '/^chrony/,/^nginx/i good' passwd

# 匹配内容 root ,在其下一行添加 test.txt 文本中的内容
sed -i '/root/r test.txt' passwd

# 匹配内容 /bin/bash ,将包含内容的行输出至 a.txt 文件中
sed -n '/\/bin\/bash/w a.txt' passwd

(3) 修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 将 passwd 文件每一行中第一个 root 替换为 ROOT
sed -i 's/root/ROOT/' passwd

# 将 passwd 文件中 root 替换为 ROOT
sed -i 's/root/ROOT/g' passwd

# 将 passwd 文件每一行中第二个开始 root 替换为 ROOT
sed -i 's/root/ROOT/2g' passwd

# 将 passwd 文件匹配 ROOT 替换为 root,忽略大小写
sed -i 's/ROOT/root/ig' passwd

# 正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词:
echo this is a test line | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]

(4) 反向引用

作用:重新使用匹配到的内容,并进行进一步的变更操作。

方式:反向引用有两种方式,分别是&反向引用和\1反向引用,

&反向引用

1
2
# 将匹配内容 r..t (.表示任意字符) 替换为 r..tWWW
sed -i 's/r..t/&WWW/g' passwd

\1反向引用

1
2
3
# 将匹配内容 sbin  替换为 sbinOOO
sed -i 's/\(sbin\)/\1OOO/g' passwd
#注意:匹配的内容需要用括号()括起来,括号需要转义

优势:\1反向引用相对于&优势是可以将引用内容部分替换

1
2
3
# 将匹配内容 ntA... (.表示任意字符) 替换为 ntABBP
sed -i 's/\(ntA\).../\1BBp/g' passwd
# 注意:匹配到内容后需要引用的部分需要用括号()括起来,括号需要转义

(5)注意事项:

a. 使用sed进行变量内容替换时,需要用双引号进行操作

1
sed -i "s/$a/$b/g" passwd

b. sed引用自定义变量时,如果外面使用单引号,则自定义变量也需要使用单引号

1
sed -i 's/'$a'/'$b'/g' passwd