在前头讲述vim的时候,提到了vim的末行命令(ex模式命令)就是sed命令(文本编辑工具),它和grep命令(文本搜索)、awk命令(文件格式化工具)并称为文本处理三剑客。当在vim中时,我们可以通过在编辑模式下输入“:”来使用一些命令,而这些命令也可以通过“sed”命令来在shell命令行模式下使用。sed命令全名为:Stream EDitor(流编辑器),以行为单位对一个或多个文件进行编辑处理。每一次sed都会处理给定文件中的一行内容。在sed处理文本时,将正在处理的当前行存储到临时的缓冲区中,称为“模式空间”;用当前行去匹配给定的PATTERN,如果能匹配,则使用command编辑处理;如果不匹配,则默认输出至标准输出;然后继续处理下一行,直到文件的末尾。与此相似的是在bash脚本中的“while read LINES”命令,举例如下:

首先创建一个文本,包含以下内容:

[root@localhost 20170610]# cat test 
qwe
asd
zxc

然后创建包含如下内容的脚本并运行:

[root@localhost 20170610]# cat whileReadLine 
#!/bin/bash
while read LINES
do
echo $LINES
done <./test
[root@localhost 20170610]# bash whileReadLine
qwe
asd
zxc

    在这里我们可以看到“while”将“./test”文件中的内容按行读入并进行处理。

        但是这种方法过于麻烦,所以我们需要一个更加方便、快捷,功能更加强大的方法——“sed”命令。


sed命令:

sed - stream editor for filtering and transforming text

sed [OPTION]... 'script' [input-file]...

常用选项:

-n, --quiet, --silent:对于不能匹配模式的行,默认不输出到屏幕;

-e script, --expression=script:多条件编辑;

-f script-file, --file=script-file:从指定的script-file中读取脚本

注意:script-file为一个能够定位到脚本文件的路径,最好为绝对路径

-i[SUFFIX], --in-place[=SUFFIX]:原文件直接编辑操作;

注意:默认情况下,sed的所有处理行为不会影响源文件的内容;

-r, --regexp-extended:使sed支持扩展正则表达式;


script:

'AddressesCommand'

Addresses(地址定界):

1.空地址:对所有文件的所有行进行处理;

2.单地址:sed对于能够匹配该地址的那唯一一行进行处理;

num:表示行号;

/pattern/:能够匹配该模式的所有行;

$:表示文档最后一行

3.地址范围:

addr1,addr2:从addr1开始到addr2结束的中间所有行;

例如:2,8:从第二行到第八行

first~step:从first标记的行号开始,以step所代表的数字为步长;

例如:2~5:第2行和第7(2+5)行

addr1,+N:从addr1开始,包括addr1所在行,并继续向后计算N行;

例如:2,+7相当于2到9(2+7)行

addr1,~N:从addr1开始,包括addr1所在行,向后计算N的大于addr1的最小整数倍的行;

例如:2,~5相当于从第2行到第5行

又例如:3,~4相当于从第3行到4的大于3的最小倍数(也就是4)行

还例如:5,~3相当于从第5行到3的大于5的最小倍数(也就是6)行

/pattern1/,/pattern2/:从被pattern1匹配的第一行开始计算,一直到被/pattern2/匹配到的第一行结束;


Command(处理命令):

=:显示被模式匹配的行的行号

例如:sed -n '/^$/=' /etc/grub2.cfg

a \text:在被模式匹配的行的后面追加text的内容,支持使用\n换行,从而实现多行追加;

i \text:在被模式匹配的行的前面插入text的内容,支持使用\n换行,从而实现多行插入;

c \text:将被模式匹配的行的修改为text的内容,支持使用\n换行,从而实现一行变多行;

d:在模式空间中删除被模式匹配的行;这样的行不能再进行标准输出;

注意:在使用d命令的时候,不宜使用-n选项;

p:显示模式空间中被模式匹配的行;

注意:在使用p命令的时候,通常会搭配-n选项;

w filepath:将模式空间中被模式匹配的行,另存到filepath文件中;

r filepath:将filepath文件的内容追加至模式空间中被模式匹配的行之后;

!Command:在模式空间中被模式匹配的行,不执行Command命令;相反,未被模式匹配的行,参会执行Command命令

s///:查找替换,分隔符可以任意更换,只要相同即可;

s@@@, s###, s,,,

s/pattern/text/[control]

s@/etc/fstab@/etc/mtab@

pattern:计划查找并替换的内容

text:要替换的结果

control:如何进行替换,可用的选项有:

g:行内全部替换

p:显示替换成功的行

w filepath:将替换成功的行另存到filepath文件中;


支持后向引用:

s/\(string\)/&/

s/\(string\)/\1/


高级编辑命令:

h: 把模式空间中的内容覆盖至保持空间中

H:把模式空间中的内容追加至保持空间中

g: 从保持空间取出数据覆盖至模式空间

G:从保持空间取出内容追加至模式空间

x: 把模式空间中的内容与保持空间中的内容进行互换

n: 读取匹配到的行的下一行覆盖至模式空间

N:追加匹配到的行的下一行至模式空间

d: 删除模式空间中的行

D:删除多行模式空间中的所有行


示例:

sed -n 'n;p' FILE

sed '1!G;h;$!d' FILE

sed '$!N;$!D' FILE

sed '$!d' FILE

sed ‘G’ FILE

sed ‘g’ FILE

sed ‘/^$/d;G’ FILE

sed 'n;d' FILE

sed -n '1!G;h;$p' FILE


        对于这个sed命令,在使用的时候需要将选项和sed命令中的处理命令结合起来使用,一些常用的功能举例如下:

    首先创建一个文本文件,包含以下内容:

[root@localhost 20170611]# cat test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


        使用这个命令,会显示匹配到的行,因为加上了“-n”选项,所以仅仅输出一个匹配到的行号“7”,在单引号中的两个斜杠之间是匹配的模式,使用正则表达式来匹配

[root@localhost 20170611]# sed -n '/shutdown/=' test1
7
[root@localhost 20170611]#

“p”命令

    如果想要显示行中的内容,使用“p”命令,显示第五行:

[root@localhost 20170611]# sed -n '5p' test1
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin


    还可以显示其他的行,具体的使用请查看上面提到的地址定界:

[root@localhost 20170611]# sed -n '1,5p' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost 20170611]# sed -n '1~5p' test1
     1root:x:0:0:root:/root:/bin/bash
     6sync:x:5:0:sync:/sbin:/bin/sync
[root@localhost 20170611]#



“a”命令

    在第二行的下面添加内容(此时需要去掉“-n”选项才能更清楚的看到效果):

[root@localhost 20170611]# sed '2a abcd' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
abcd
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


    还可以同时在多行下同时加上内容,同时在第二行到第四行的下面加上内容:

[root@localhost 20170611]# sed '2,4a abcd' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
abcd
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
abcd
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
abcd
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


    如果想要在同一行的下面同时加上多行,使用“\n”进行换行:

[root@localhost 20170611]# sed '2,4a abcd\nefg' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
abcd
efg
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
abcd
efg
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
abcd
efg
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


    “i”命令与“a”命令几乎相同,“a”命令是在一行的后面添加一行,“i”命令是在一行的前面添加一行,在这里就不再举例


“c”命令

    这个命令可以用来进行内容的替换,比如将第二行的内容替换掉:

[root@localhost 20170611]# sed '2c abcd' test1
     1root:x:0:0:root:/root:/bin/bash
abcd
     3daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4adm:x:3:4:adm:/var/adm:/sbin/nologin
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


        同“a”等命令相似,这个命令也可以同时修改多行,比如同时替换第三行到第四行的内容,不过替换后的内容只会显示一次,不会重复:

[root@localhost 20170611]# sed '3,4c abcd' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
abcd
     5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6sync:x:5:0:sync:/sbin:/bin/sync
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#


“d”命令

    删除特定的行,比如删除第三行到第六行:

[root@localhost 20170611]# sed '3,6d' test1
     1root:x:0:0:root:/root:/bin/bash
     2bin:x:1:1:bin:/bin:/sbin/nologin
     7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8halt:x:7:0:halt:/sbin:/sbin/halt
     9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@localhost 20170611]#

    删除第二行到最后一行:

[root@localhost 20170611]# sed '2,$d' test1
     1root:x:0:0:root:/root:/bin/bash
[root@localhost 20170611]#

“s”命令

        这个命令可以用来进行字符的替换,比如将文本中的所有“:”替换成“@@@”:

[root@localhost 20170611]# sed 's/:/@@@/g' test1
     1root@@@x@@@0@@@0@@@root@@@/root@@@/bin/bash
     2bin@@@x@@@1@@@1@@@bin@@@/bin@@@/sbin/nologin
     3daemon@@@x@@@2@@@2@@@daemon@@@/sbin@@@/sbin/nologin
     4adm@@@x@@@3@@@4@@@adm@@@/var/adm@@@/sbin/nologin
     5lp@@@x@@@4@@@7@@@lp@@@/var/spool/lpd@@@/sbin/nologin
     6sync@@@x@@@5@@@0@@@sync@@@/sbin@@@/bin/sync
     7shutdown@@@x@@@6@@@0@@@shutdown@@@/sbin@@@/sbin/shutdown
     8halt@@@x@@@7@@@0@@@halt@@@/sbin@@@/sbin/halt
     9mail@@@x@@@8@@@12@@@mail@@@/var/spool/mail@@@/sbin/nologin
    10uucp@@@x@@@10@@@14@@@uucp@@@/var/spool/uucp@@@/sbin/nologin
[root@localhost 20170611]#


        如果替换后头的字符为空,就可以当成删除的命令,比如去掉“@@@”即为删除“:”:

[root@localhost 20170611]# sed 's/://g' test1
     1rootx00root/root/bin/bash
     2binx11bin/bin/sbin/nologin
     3daemonx22daemon/sbin/sbin/nologin
     4admx34adm/var/adm/sbin/nologin
     5lpx47lp/var/spool/lpd/sbin/nologin
     6syncx50sync/sbin/bin/sync
     7shutdownx60shutdown/sbin/sbin/shutdown
     8haltx70halt/sbin/sbin/halt
     9mailx812mail/var/spool/mail/sbin/nologin
    10uucpx1014uucp/var/spool/uucp/sbin/nologin
[root@localhost 20170611]#


        有点时候“/”这个符号会重复,此时我们可以换一个符号,只要三个一样即可,比如将所有的“/”替换为“$”:

[root@localhost 20170611]# sed 's@/@$@g' test1
     1root:x:0:0:root:$root:$bin$bash
     2bin:x:1:1:bin:$bin:$sbin$nologin
     3daemon:x:2:2:daemon:$sbin:$sbin$nologin
     4adm:x:3:4:adm:$var$adm:$sbin$nologin
     5lp:x:4:7:lp:$var$spool$lpd:$sbin$nologin
     6sync:x:5:0:sync:$sbin:$bin$sync
     7shutdown:x:6:0:shutdown:$sbin:$sbin$shutdown
     8halt:x:7:0:halt:$sbin:$sbin$halt
     9mail:x:8:12:mail:$var$spool$mail:$sbin$nologin
    10uucp:x:10:14:uucp:$var$spool$uucp:$sbin$nologin
[root@localhost 20170611]#



        在上面的例子中我都是使用的字符串进行匹配,但是在实际的使用中我们可以将字符串替换为正则表达式来进行匹配(正则表达式查看原先的博客)