sed是什么
sed是Linux下一款功能强大的非交互流式文本编辑命令,可以对文本文件进行增、删、改、查等操作,支持按行、按字段、按正则匹配文本内容,特别适合于大文件的编辑。本文主要介绍sed的演示sed的命令格式、常用命令和脚本操作等。
sed命令格式
使用man sed命令可以查看到,sed命令格式如下所示:
sed [OPTION]... {script-only-if-no-other-script} [input-file]...
sed的常用选项:
-r:使用扩展正则表达式
-e script, --expression=script:它告诉sed将下一个参数解释为一个sed指令,只有当命令行上给出多个sed指令时才需要使用-e选项
-f, script-file, --file=script-file:后跟保存了sed指令的文件
sed SCRIPT
sed 命令的核心, SCRIPT由一系列的sed commands(sed命令)组成,使用-e,-f等选项将一系列的sed命令添加到脚本当中。在循环处理的过程中,对模式空间的内容使用脚本进行处理作为结果。
-i[SUFFIX], --in-place[=SUFFIX]:直接对内容进行修改,不加-i时默认只是预览,不会对文件做实际修改,当然,SUFFIX是可选的,如果加入SUFFIX,就会在改动原文件之前会将其以SUFFIX为文件名后缀备份一份。例如sed -i".bak" test.txt会在处理前将test.txt备份为test.txt.bak
-n, --quiet, --silent:取消默认输出,sed默认会输出所有文本内容,使用-n参数后只显示处理过的
请注意: 如果没有 -e,--expression, -f 或者 --file 选项,第一个非选项参数或作为sed script解释,所有剩下的参数都认为是输入的文件名称,如果没有指定输入文件名称,那么sed命令会使用标准输入
Sed Command命令
[addr]X[options]
简单理解,它由定位 + 编辑命令组成,addr就是定位命令 addr
addr是一个可选的能否标识行的地址,可以是一个单独的方号、正则、行范围
- 单独一个数字标识行号。
/^#hello/表示以#hello开头的行。/X$/表示以X结尾的行。$表示最后一行。x,/pattern/,从第 x 行到与 pattern 匹配的所有行x,y!,匹配不包括 第x行 至 第y行的行/pattern/,x,从与 pattern 匹配的行到第 x 行间的所有行0,addr2,匹配从开始至addr2的行,仅GUN sed支持,5,7表示5-7行。addr1,~N,匹配从addr1开始的N行,仅GUN sed支持addr1,+N,匹配addr1和它后面的N行,仅GUN sed支持,5,+6 表示第5行和跟着第5行后面的6行
编辑命令
编辑命令只能针对addr匹配的行进行处理,常见的选项如下:
-
a:新增, [options]为要增加的内容,新增的内容为单独一行,在当前行的下方,如果需要增加多行,行与行之间使用\n分割。 -
c:取代, [options]为新的内容。 -
i:插入, [options]为要插入的内容,插入的内容为单独一行,在当前行的上方,同样可以使用\n实现插入多行。 -
d:删除, 不需要[options]。 -
p:列印,不需要[options],将当前模式空间的内容打印出来,通常与参数 sed -n配合使用。 -
s:取代,最复杂的一个命令,[options]为正则表达式/REGEXP/REPLACEMENT/[FLAGS],例如:s/old/new/g表示将old换为new,g表示进行全局替换,默认为替换第一处。/old/new/g为s的option。-
REGEXP
正则表达式,匹配的内容会被REPLACEMENT替换。
-
REPLACEMENT
字符串,直接替换
-
\N N可以为1~9, 引用匹配分组的内容。
sed -e 's/#(Port.+)/\1/g' /etc/ssh/sshd_config
sed -r -e 's/#(Port.+)/\1/g' /etc/ssh/sshd_config
上面的两行等价将以#PORT开始的行#去掉,使用-r选项能够避免使用() -
&引用整个匹配内容
sed -e s/^Port/#&/g /etc/ssh/sshd_config
匹配以Port开头的行,并在前面加上#。 -
\L将后面的内容转为小写,直到遇到\U或\E结束 -
\l将后面的一个字符转为小写 -
\U将后面的内容转为大写,直到遇到\L或\E结束 -
\u将后面的一个字符转为大写 -
\E结束\L,\U的转换
sed -r -e 's/(\b[^\s])/\u\1/g' /etc/ssh/sshd_config
将所有单词首字母大写。
-
-
FLAGS
g全局替换p打印=打印行号
-
-
y:转换,[options]为转换字典/src/dst/,将出现的每个src中的字符替换为dst中相应的字符,y/abc#/ABC%/a->A,b->B,c->C,#->% -
q:退出,[options]为返回值,退出后直接结束输入流的处理。 -
{},命令组,组内命令用分号;分隔
sed命令例子
- 插入行 在第三行后面插入hello
guanwu@master:~/learnshell/sed$ cat 1.txt
111
222
333
444
555
666
guanwu@master:~/learnshell/sed$ sed '3ahello' 1.txt
111
222
333
hello
444
555
666
guanwu@master:~/learnshell/sed$
sed -e '/world$/a====new line====' test4.txt 在 world结尾的下一行添加====new line====
guanwu@master:~/learnshell/sed$ cat test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -e '/world$/a====new line====' test4.txt
4444444111
66666helloworld
====new line====
hihihihih
gagagagaga
world hello
c++ java hello world
====new line====
1 2 3 34 45
guanwu@master:~/learnshell/sed$
sed -e '/world$/i====new line====' test4.txt 在 world结尾的前一行添加====new line====
guanwu@master:~/learnshell/sed$ sed -e '/world$/i====new line====' test4.txt
4444444111
====new line====
66666helloworld
hihihihih
gagagagaga
world hello
====new line====
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$
在最后一行前插入 hello java
sed '$ihello java' test4.tx
guanwu@master:~/learnshell/sed$ sed '$ihello java' test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello
c++ java hello world
hello java
1 2 3 34 45
- 删除 删除1~3行
guanwu@master:~/learnshell/sed$ sed -e '1,3d' 1.txt
444
555
666
从第1行开始,每隔两行删除一行,删除奇数行
sed '1~2d' test4.txt
guanwu@master:~/learnshell/sed$ sed '1~2d' test4.txt
66666helloworld
gagagagaga
c++ java hello world
删除删除空行可以使用命令 sed /^$/d
- 打印
sed -n -e '1,3p' .txt 打印1~3行
guanwu@master:~/learnshell/sed$ sed -n -e '1,3p' 1.txt
111
222
333
sed -n -e '/^abc/p;a newline' 打印abc开始的行,每行后面添加newline
guanwu@master:~/learnshell/sed$ cat 2.txt
111
222
abc333
444
555
666
abc777
888
abc999
guanwu@master:~/learnshell/sed$ sed -n -e '/^abc/p;a newline' 2.txt
newline
newline
abc333
newline
newline
newline
newline
abc777
newline
newline
abc999
newline
打印匹配4的行
guanwu@master:~/learnshell/sed$ cat test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -n '/4/p' test4.txt
4444444111
1 2 3 34 45
打印文件的行号,和打印匹配的行号和内容
guanwu@master:~/learnshell/sed$ sed -n '=' test4.txt
1
2
3
4
5
6
7
guanwu@master:~/learnshell/sed$ sed -n '/gagaga/{=;p}' test4.txt
4
gagagagaga
guanwu@master:~/learnshell/sed$
打印 匹配444 到 匹配gaga的行
sed -n '/444/,/gaga/p' test4.txt
guanwu@master:~/learnshell/sed$ cat test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -n '/444/,/gaga/p' test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
- 替换
sed -e 's/^/#/g' 2.txt 在所有行前添加#符号
guanwu@master:~/learnshell/sed$ sed -e 's/^/#/g' 2.txt
#111
#222
#abc333
#444
#555
#666
#abc777
#888
#abc999
sed -e 's/^[^#]/#&/' sample.txt 在所有非#开头的行添加#符号,使用&符号是为了避免误删开头的字符,如果不加&,则会出现 #nclude<stdio.h>这样的结果
guanwu@master:~/learnshell/sed$ cat sample.txt
include<stdio.h>
#include<other.h>
#include<test.h>
include<test2.h>
guanwu@master:~/learnshell/sed$ sed 's/^[^#]/#&/' sample.txt
#include<stdio.h>
#include<other.h>
#include<test.h>
#include<test2.h>
sed -r 's/(.*)/\U\1/g' 3.txt 将字母全部转为大写
guanwu@master:~/learnshell/sed$ cat 3.txt
abc
hello World
This is a nice day
haha, i am Fine
guanwu@master:~/learnshell/sed$ sed -r 's/(.*)/\U\1/g' 3.txt
ABC
HELLO WORLD
THIS IS A NICE DAY
HAHA, I AM FINE
sed -r -e '/^#/d' sample.txt 删除以#开头的行
guanwu@master:~/learnshell/sed$ cat sample.txt
include<stdio.h>
#include<other.h>
#include<test.h>
include<test2.h>
guanwu@master:~/learnshell/sed$ sed -r -e '/^#/d' sample.txt
include<stdio.h>
include<test2.h>
将**#PasswordAuthentication yes** 去掉注释,并将yes改为no
sed -n -r -e 's/^.{0,1}(PasswordAuthentication ).{2,3}$/\1no/gp' sample.config
guanwu@master:~/learnshell/sed$ cat sample.config
#PasswordAuthentication yes
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication, then enable this but set PasswordAuthentication
guanwu@master:~/learnshell/sed$ sed -n -r -e 's/^.{0,1}(PasswordAuthentication ).{2,3}$/\1no/gp' sample.config
PasswordAuthentication no
guanwu@master:~/learnshell/sed$
在文件的每一行后面添加haha
sed 's/$/&'haha'/' test2.txt
guanwu@master:~/learnshell/sed$ sed 's/$/&'haha'/' test2.txt
ddddhaha
eeeehaha
fffffhaha
gggghaha
dddddfhaha
helloworldhagagahaha
guanwu@master:~/learnshell/sed$
- 从文件中读取内容
sed 'r test1.txt' test2.txt #将文件test1.txt中的内容,读入test2.txt中,会在test2.txt中的每一行后都读入test1.txt的内容
guanwu@master:~/learnshell/sed$ cat test2.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test1.txt
aaa
bbb
ccc
guanwu@master:~/learnshell/sed$ cat test2.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ sed 'r test1.txt' test2.txt
dddd
aaa
bbb
ccc
eeee
aaa
bbb
ccc
fffff
aaa
bbb
ccc
gggg
aaa
bbb
ccc
在第二行后读入 test1.txt的内容
sed '2r test1.txt' test2.txt
guanwu@master:~/learnshell/sed$ sed '2r test1.txt' test2.txt
dddd
eeee
aaa
bbb
ccc
fffff
gggg
匹配ddd后的行插入test1.txt的内容
guanwu@master:~/learnshell/sed$ sed '/ddd/r test1.txt' test2.txt
dddd
aaa
bbb
ccc
eeee
fffff
gggg
最后一行插入test1.txt的内容
sed '$r test1.txt' test2.txt
guanwu@master:~/learnshell/sed$ sed '$r test1.txt' test2.txt
dddd
eeee
fffff
gggg
aaa
bbb
ccc
guanwu@master:~/learnshell/sed$
- 向文件中写入内容 将test2.txt的内容写入到test3.txt中,没有test3.txt时,会自动创建
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test3.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$
将test2.txt的第二行写入test4.txt中
guanwu@master:~/learnshell/sed$ sed '2w test4.txt' test2.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test4.txt
eeee
guanwu@master:~/learnshell/sed$
匹配ddd或fff的行写入 test6.txt中
guanwu@master:~/learnshell/sed$ cat test2.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ sed -n '/ddd\|fff/w test6.txt' test2.txt
guanwu@master:~/learnshell/sed$ cat test6.txt
dddd
fffff
guanwu@master:~/learnshell/sed$
匹配eee到结尾的行写入到test7.txt中
guanwu@master:~/learnshell/sed$ sed -n '/eee/,$w test7.txt' test2.txt
guanwu@master:~/learnshell/sed$ cat test7.txt
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$