sed编辑器
sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。
sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中。
sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
sed工作流程
sed的工作流程主要包括读取、执行和显示三个过程:
- 读取: sed从输入流 (文件、管道、标准输入) 中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space )。
- 执行: 默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行。
- 显示: 发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行, 直至所有内容被处理完。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非使用"sed -i"修改源文件、或使用重定向输出到新的文件中。
sed命令格式
格式:
sed -e '操作' 文件1 文件2
sed -n -e '操作' 文件1 文件2
sed -f 脚本文件 文件1 文件2
sed -i -e '操作' 文件1 文件2
执行多条命令的三种方法:
sed -n -e '操作1' -e '操作2' 文件
sed -n -e '操作1;操作2' 文件
sed -e 'n{
操作1
操作2
......
}' 文件1
常用选项:
| 选项 | 作用 |
|---|---|
| -e 或--expression= | 表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用 |
| -f 或--file= | 表示用指定的脚本文件来处理输入的文本文件 |
| -h 或--help | 显示帮助 |
| -n、--quiet或--silent | 禁止sed编辑器输出,但可以与p命令一起使用完成输出 |
| -i | 直接修改目标文本文件 |
常用操作:
| 操作 | 作用 |
|---|---|
| s | 替换,替换指定字符 |
| d | 删除,删除选定的行 |
| a | 增加,在当前行下方增加一行指定内容 |
| i | 插入,在选定行上方插入一行指定内容 |
| c | 替换,将选定行替换为指定内容 |
| y | 字符转换,转换前后的字符长度必须相同 |
| p | 打印行内容。如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其通常与"-n"选项一起使用 |
| = | 打印行号 |
| l (小写L) | 打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t) |
sed的核心功能:增删改查(可配合正则表达式)
查: p
删: d
改: s(字符串替换)、c(整行替换)、y(对应字符进行替换,效果类似tr命令)
增: i(在行前插入内容)、a(在行后添加内容)、r(在行后读入文件的内容)
复制粘贴:H(复制)、d(删除)、G(粘贴到指定行下方)
查找打印(p)
1、sed编辑器默认输出行内容,-n选项可以禁止输出。如果不加-n,却使用p操作,那么每行内容会打印两次。
sed -e "p" :每行内容打印两次。
sed -n "p" :每行内容只打印一次。
[root@localhost ~]# cat 1.txt
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# sed -e 'p' 1.txt
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
[root@localhost ~]# sed -n -e 'p' 1.txt
1
2
3
4
5
6
7
8
9
10
2、'n' 打印行号。
sed -n '=' :只打印行号。
sed -e 'n' : 打印行号和行内容。
sed -n '=;p' :打印行号和行内容。
[root@localhost ~]# sed -n '=' 2.txt
1
2
3
4
5
6
7
8
9
[root@localhost ~]# sed -e '=' 2.txt
1
a
2
b
3
c
4
d
5
e
6
f
7
g
8
h
9
i
3、sed 执行多条命令的三种方法。
以打印行号和行内容为例:
#方法一
sed -n -e '=' -e 'p' file.txt
#方法二
sed -n -e '=;p' file.txt
#方法三:换行操作
sed -n '
=
p
' file.txt
4、'l' 打印文本即隐藏字符(结束符$,制表符\t)。
[root@localhost ~]# sed -n 'l' 1.txt
1$
2$
3$
4$
5$
6$
7$
8$
9$
10$
sed 对指定行进行操作
两种方法:
- 以数字形式表示行区间;
- 用文本模式(字符串)来过滤出行(一般结合正则表达式)。
以数字形式表示行区间:
| 操作 | 含义 |
|---|---|
| '1p' | 打印第一行 |
| '$p' | 打印最后一行 |
| '1,3p' | 打印连续行,打印第一行到第三行 |
| '6,$p' | 打印第六行到最后一行 |
| '1,+3p' | 打印第一行加后面三行(即打印第一到第四行) |
| '5q' | 打印前五行后退出 |
| 'p;n' | 打印奇数行 |
| 'n;p' | 打印偶数行 |
使用字符串匹配出行:
| 操作 | 含义 |
|---|---|
| '/root/p' | 打印包含root的行 |
| '/root/!p' | 打印不包含root的行。! 表示取反 |
| '/^root/p' | 打印以root开头的行 |
| '/bash$/' | 打印以bash结尾的行 |
| '/root l bash/p' | 打印包含root或bash的行。"l"是扩展正则表达式的元字符,要使用sed -r |
| '6,/root/p' | 打印第6行到第一个包含root的行 |
以数字形式表示行区间
1、打印单行。
[root@localhost ~]# sed -n '1p' 2.txt
a
[root@localhost ~]# sed -n '3p' 2.txt
c
[root@localhost ~]# sed -n -e '4p' -e '6p' 2.txt
d
f
2、打印连续的行,使用逗号。
[root@localhost ~]# sed -n '2,4p' 2.txt
b
c
d
[root@localhost ~]# sed -n '5,$p' 2.txt
e
f
g
h
i
3、'1,+3p',打印第1行加后面3行(即打印第1~4行)。
[root@localhost ~]# sed -n '1,+3p' 2.txt
a
b
c
d
4、使用sed输出奇数行或者偶数行。 'n' :next,读取下一行。
'p' :打印当前所在行。
[root@localhost ~]# sed -n 'p;n' 2.txt
a
c
e
g
i
[root@localhost ~]# sed -n 'n;p' 2.txt
b
d
f
h
5、打印除了第一行以外的奇数行。
[root@localhost ~]# sed -n '2,${n;p}' 2.txt
c
e
g
i
6、比较 'p;n;p' 和 'n;p;n' 。
[root@localhost ~]# sed -n 'p;n;p' 2.txt
a
b
c
d
e
f
g
h
i
[root@localhost ~]# sed -n 'n;p;n' 2.txt
b
e
h
使用正则表达式,匹配行内容
注意:sed 使用扩展正则表达式时,要加 -r 。
例1:
先将/etc/passwd 文件复制到家目录下并改名为pass.txt
[root@localhost ~]# cp /etc/passwd pass.txt
[root@localhost ~]# sed -n '/root/p' pass.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n '/^root/p' pass.txt
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# sed -n '/bash$/p' pass.txt
root:x:0:0:root:/root:/bin/bash
carus:x:1000:1000:carus:/home/carus:/bin/bash
例2:
[root@localhost ~]# sed -n '6,/root/p' pass.txt
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n '6,/root/=' pass.txt
6
7
8
9
10
例3:
sed -r 支持扩展正则表达式。同时在 使用{n}、{n,}、{n,m}时,括号{}前不需要加反斜杠\ 。
[root@localhost ~]# sed -n -r '/ro{2,}t/p' pass.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n -r '/root|bash/p' pass.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
carus:x:1000:1000:carus:/home/carus:/bin/bash
删除(d)
例1:
以数字形式表示行区间。
[root@localhost ~]# cat 2.txt
a
b
c
d
e
f
g
h
i
[root@localhost ~]# sed '3d' 2.txt //删除第3行
a
b
d
e
f
g
h
i
[root@localhost ~]# sed '5,8d' 2.txt //删除第5~8行
a
b
c
d
i
[root@localhost ~]# sed '$d' 2.txt //删除最后一行
a
b
c
d
e
f
g
h
[root@localhost ~]# sed 'd' 2.txt //删除所有行
[root@localhost ~]# sed '1,+3d' 2.txt //删除第1行及后面3行(即删除第1~4行)
e
f
g
h
i
[root@localhost ~]# sed '6,$d' 2.txt //删除第6行到最后一行
a
b
c
d
e
[root@localhost ~]# sed '6!d' 2.txt //除了第6行,其他都删除
f
[root@localhost ~]# sed '6,$!d' 2.txt //除了第6行到最后一行,其他都删除
f
g
h
i
例2:
通过字符串匹配出想要的行。
[root@localhost ~]# sed '/e$/d' 3.txt
two
four
six
seven
eight
ten
[root@localhost ~]# sed '/e$/!d' 3.txt
one
three
five
nine
例3:
'/字符串1/,/字符串2/d' :从第一个匹配的位置打开删除功能,到第二个匹配的位置删完后关闭删除功能。之后继续按这个规则向下查找删除。
[root@localhost ~]# sed '/1/,/3/d' 1.txt
4
5
6
7
8
9
[root@localhost ~]# sed '/2/,/4/d' 1.txt
1
5
6
7
8
9
10
修改替换(s c y)
s:替换字符串
c:整行替换
y:字符替换,替换前后的字符串长度必须相同
替换字符串 s
格式:
行范围 s/旧字符串/新字符串/替换标记
#4种替换标记:
数字:表明新字符串将替换第几处匹配的地方
g:表面新字符串将会替换所有匹配的地方
p:打印与替换命令匹配的行,与-n一起使用
w 文件:将替换的结果写入文件中
例1:
[root@localhost ~]# sed -n '/root/p' pass.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n 's/root/aaa/p' pass.txt
aaa:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/aaa:/sbin/nologin
[root@localhost ~]# sed -n 's/root/aaa/2p' pass.txt
root:x:0:0:aaa:/root:/bin/bash
[root@localhost ~]# sed -n 's/root/aaa/3p' pass.txt
root:x:0:0:root:/aaa:/bin/bash
[root@localhost ~]# sed -n 's/root/aaa/gp' pass.txt
aaa:x:0:0:aaa:/aaa:/bin/bash
operator:x:11:0:operator:/aaa:/sbin/nologin
例2:
[root@localhost ~]# sed -n 's/root//gp' pass.txt
:x:0:0::/:/bin/bash
operator:x:11:0:operator:/:/sbin/nologin
[root@localhost ~]# echo 000010101 | sed 's/^0*//'
10101
例3:
将root开头的行进行注释(在开头加上#);
在包含root的行的行尾加上#
[root@localhost ~]# sed -n '/^root/p' pass.txt //打印所有以root开头的行
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# sed -n '/^root/ s/^/#/p' pass.txt //过滤出以root开头的行,在行首加上#
#root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# sed -n '/root/p' pass.txt //打印包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n '/root/ s/$/#/p' pass.txt //在包含root的行的行尾加上#
root:x:0:0:root:/root:/bin/bash#
operator:x:11:0:operator:/root:/sbin/nologin#
例4:另一种替换方式
将包含root内容的行进行注释:
用正则表达式匹配包含root的整行内容,之后在整行内容前加#。&代表前面使用正则表达式匹配到的整行内容。
[root@localhost ~]# sed -n '/root/ s/^/#/p' pass.txt
#root:x:0:0:root:/root:/bin/bash
#operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# sed -n 's/.*root.*/#&/p' pass.txt
#root:x:0:0:root:/root:/bin/bash
#operator:x:11:0:operator:/root:/sbin/nologin
例5:指定分隔符
当字符串中包含"/"时,需要在前面加上转义符\,避免和分隔符"/"混淆。这样操作非常麻烦,且容易眼花看错,此时可以自己指定分隔符。
s后面的第一个字符就是分隔符,3个分隔符要保持一致,如果遇到跟分隔符相同的字符需要使用 \ 转义成普通字符。
[root@localhost ~]# sed -n 's#/bin/bash#/sbin/nologin#p' pass.txt
root:x:0:0:root:/root:/sbin/nologin
carus:x:1000:1000:carus:/home/carus:/sbin/nologin
[root@localhost ~]# sed -n 's!/bin/bash!/sbin/nologin!p' pass.txt
root:x:0:0:root:/root:/sbin/nologin
carus:x:1000:1000:carus:/home/carus:/sbin/nologin
[root@localhost ~]# sed -n 's8/bin/bash8/sbin/nologin8p' pass.txt
root:x:0:0:root:/root:/sbin/nologin
carus:x:1000:1000:carus:/home/carus:/sbin/nologin
整行替换 c
例:
将包含字符串fo的行,整体替换成66。
[root@localhost ~]# sed '/fo/c 66' 3.txt
one
two
three
66
five
six
seven
eight
nine
ten
单字符替换 y
使用y,是对单个字符进行替换,每个字符需要一一对应,不是整体替换。前后字符串长度需要一致,不然会报错。 例:
遇到n替换成2,遇到o替换成5。
[root@localhost ~]# sed 'y/no/25/' 3.txt
52e
tw5
three
f5ur
five
six
seve2
eight
2i2e
te2
[root@localhost ~]# sed 'y/no/255/' 2.txt
sed:-e 表达式 #1,字符 9:“y”命令的字符串长度不同
增加(a i r)
a:在行后添加内容
i:在行前插入内容
r:在行后读入文件内容
在行后添加内容 a
例1:在第一行下方添加一行内容
[root@localhost ~]# sed '1a 22' 2.txt
a
22
b
c
d
e
f
g
h
i
例2:在第1~3行,每行下方添加一行内容
[root@localhost ~]# sed '1,3a 22' 2.txt
a
22
b
22
c
22
d
e
f
g
h
i
例3:在最后一行的下方,添加一行内容
[root@localhost ~]# sed '$a 66' 2.txt
a
b
c
d
e
f
g
h
i
66
例4:在第一行下方添加3行内容
[root@localhost ~]# sed '1a 22\n33\n44' 2.txt
a
22
33
44
b
c
d
e
f
g
h
i
在行前插入内容 i
[root@localhost ~]# sed '1i 77' 2.txt
77
a
b
c
d
e
f
g
h
i
[root@localhost ~]# sed '1,3i 77' 2.txt
77
a
77
b
77
c
d
e
f
g
h
i
在行后读入文件内容 r
[root@localhost ~]# cat 4.txt
km
[root@localhost ~]# sed '6r 4.txt' 2.txt
a
b
c
d
e
f
km
g
h
i
复制粘贴
比较vi/vim编辑器和 sed编辑器:
#vi//vim编辑器:
命令模式
dd p 剪切 粘贴
yy p 复制 粘贴
末行模式
:1,3 co 10 复制 粘贴(将第1~3行复制粘贴到第10行下方)
:1,3 m 10 剪切 粘贴(将第1~3行剪切到第10行下方)
#sed命令:
H复制、d删除、G粘贴到指定行下方
例1:剪切粘贴 H复制,d删除,通过”复制后删除“来达到剪切的效果。
[root@localhost ~]# sed '1,3 {H;d};$G' 2.txt
d
e
f
g
h
i
a
b
c
[root@localhost ~]# sed '1,3 {H;d};5G' 2.txt
d
e
a
b
c
f
g
h
i
例2:复制粘贴
将1到3行复制粘贴到最后一行后面。(注意中间会多出一行空行)
[root@localhost ~]# sed '1,3 H;$G' 2.txt
a
b
c
d
e
f
g
h
i
a
b
c
文件内容中的字符串进行互换
例1:
#将2个字符串交换位置
[root@localhost ~]# echo 111222333
111222333
[root@localhost ~]# echo 111222333|sed -r 's/(111)(222)/\2\1/'
222111333
#将3个字符串交换位置
[root@localhost ~]# echo 111222333|sed -r 's/(111)(222)(333)/\3\2\1/'
333222111
#将第一个字符和最后一个字符进行互换
[root@localhost ~]# echo 111222333|sed -r 's/^(.)(.*)(.)$/\3\2\1/'
311222331
例2:
将abc123修改成123abc、321cba。
[root@localhost ~]# echo abc123| sed -r 's/(abc)(123)/\2\1/'
123abc
[root@localhost ~]# echo abc123| sed -r 's/(.)(.)(.)(.)(.)(.)/\6\5\4\3\2\1/'
321cba
[root@localhost ~]# echo abc123| sed -r 's/(a)(b)(c)(1)(2)(3)/\6\5\4\3\2\1/'
321cba
总结
1、sed的核心功能:增删改查(可配合正则表达式)
查: p
删: d
改: s(字符串替换)、c(整行替换)、y(对应字符进行替换,效果类似tr命令)
增: i(在行前插入内容)、a(在行后添加内容)、r(在行后读入文件的内容)
复制粘贴:H(复制)、d(删除)、G(粘贴到指定行下方)
复制代码
2、sed对指定行操作:
- 以数字形式表示行区间
- 用字符串来过滤行
3、 sed -i 可以直接修改文件内容,操作前建议先验证命令和备份目标文件 。
4、删除空行的三种方法:
grep -v "^$" file.txt //过滤出非空行
cat file.txt |tr -s "\n" //压缩换行符
sed '/^$/d' file.txt //删除空行
复制代码
5、查找替换:
行范围 s/旧字符串/新字符串/替换标记
s/旧字符串/新字符串/2 #代表对每行第二个匹配到的字符串进行替换
g #代表对每行所有能匹配到的字符进行替换
p #可以结合-n 选项只打印替换的行内容
w #可以把替换的行内容保存到指定的文件中
n,m s/旧字符串/新字符串/ #指定第n行到第m行,将旧字符串替换成新字符串
/字符串+正则/ s/旧字符串/新字符串/ #过滤出想要的行,之后进行替换
s/^/添加的字符/ #行首添加内容
s/$/添加的字符/ #行尾添加内容
sed -f 文件 #指定脚本文件来执行,可以在文件中定义多条操作规则
sed指定字符串的分隔符,就看s后面跟的字符,3个分隔符要保持一致,如果遇到跟分隔符相同的字符则需要使用\来转义。
例如:s#/bin/bash#/sbin/nologin#g