sed(stream editor)是一种非交互式的流编辑器,通过多种转换修改流经它的文本。但是请注意,默认情况下,sed并不会改变原文件本身,而只是对流经sed命令的文本进行修改,并将修改后的结果打印到标准输出中(也就是屏幕)。所以本节讲的所有的sed操作都只是对“流”的操作,并不会改变原文件。sed处理文本时是以行为单位的,每处理完一行就立即打印出来,然后再处理下一行,直至全文处理结束。sed可做的编辑动作包括删除、查找替换、添加、插入、从其他文件中读入数据等。

注意:要想保存修改后的文件,必须使用重定向生成新的文件。如果想直接修改源文件本身则需要使用“-i”参数。

sed命令使用的场景包括以下一些:

▪  常规编辑器编辑困难的文本。

▪  太过于庞大的文本,使用常规编辑器难以胜任(比如说vi一个几百兆的文件)。

▪  有规律的文本修改,加快文本处理速度(比如说全文替换)。

为了演示sed的用法,首先准备如下文件:

[root@localhost ~]# cat Sed.txt
this is line 1,this is First line
this is line 2,the Second line,Empty line followed

this is line 4,this is Third line
this is line 5,this is Fifth line

使用sed修改文件流的方式如下:

sed [options] 'command' file
#options是sed可以接受的参数
#command是sed的命令集(一共有25个)
#使用-e参数和分号连接多编辑命令
#该参数本身只是sed的一个简单参数,表示将下一个字符串解析为sed编辑命令
#一般情况下可以忽略,但是当sed需要传递多个编辑命令时该参数就不能少了
#下面的例子就是演示了在将this改为That的同时,还要将line改为LINE
#两个编辑命令前都要使用-e参数,如果有更多的编辑需求,以此类推即可
[root@localhost ~]# sed-e 's/this/That/g'-e 's/line/LINE/g' Sed.txt
That is LINE 1,That is First LINE
That is LINE 2,the Second LINE,Empty LINE followed

That is LINE 4,That is Third LINE
That is LINE 5,That is Fifth LINE

#使用分号连接两个都编辑命令
#上面的命令可以用分号改写为:
[root@localhost ~]# sed 's/this/That/g ; s/line/LINE/g' Sed.txt

删除

使用d命令可删除指定的行,示例如下:

#将file的第一行删除后输出到屏幕
#你应该知道如何删除第二行了
[root@localhost ~]# sed '1d' Sed.txt
this is line 2,the Second line,Empty line followed

this is line 4,this is Third line
this is line 5,this is Fifth line
#由于sed默认不修改原文件,如果希望保存修改后的文件则需要用重定向
sed '1d' Sed.txt > saved_file

#如果想直接修改文件,使用-i参数
#这里不会有任何输出,而是直接修改了源文件,删除了第一行
#Sed-i '1d' file

#删除指定范围的行(第1行到第5行)
[root@localhost ~]# sed '1,3d' Sed.txt
this is line 4,this is Third line
this is line 5,this is Fifth line

#删除指定范围的行(第一行到最后行)
[root@localhost ~]# sed '1,$d' Sed.txt
[root@localhost ~]#    #清空了Sed.txt文件
#删除最后一行
[root@localhost ~]# sed '$d' Sed.txt
this is line 1,this is First line

this is line 2,the Second line,Empty line followed this is line 4,this is Third line
#删除除指定范围以外的行(只保留第5行)
#要删除其他的行请举一反三
[root@localhost ~]# sed '5!d' Sed.txt
this is line 5,this is Fifth line

#删除所有包含Empty的行
[root@localhost ~]# sed '/Empty/d' Sed.txt
this is line 1,this is First line

this is line 4,this is Third line
this is line 5,this is Fifth line

#删除空行
[root@localhost ~]# sed '/^$/d' Sed.txt
this is line 1,this is First line
this is line 2,the Second line,Empty line followed
this is line 4,this is Third line
this is line 5,this is Fifth line

查找替换

使用s命令可将查找到的匹配文本内容替换为新的文本。

#s命令用于替换文本,本例中使用LINE替换line
#请注意每一行只有第一个line被替换了,默认情况下只替换第一次匹配到的内容
[root@localhost ~]# sed 's/line/LINE/' Sed.txt
this is LINE 1,this is First line
this is LINE 2,the Second line,Empty line followed

this is LINE 4,this is Third line
this is LINE 5,this is Fifth line

#要想每行最多匹配2个line,并改为LINE,可用如下方式
#注意到第2行中有3个line,前两个被替换了,第三个没有变化
[root@localhost ~]# sed 's/line/LINE/2' Sed.txt
this is line 1,this is First LINE
this is line 2,the Second LINE,Empty line followed

this is line 4,this is Third LINE
this is line 5,this is Fifth LINE
#s命令利用g选项,可以完成所有匹配值的替换
[root@localhost ~]# sed 's/line/LINE/g' Sed.txt
this is LINE 1,this is First LINE
this is LINE 2,the Second LINE,Empty LINE followed

this is LINE 4,this is Third LINE
this is LINE 5,this is Fifth LINE

#只替换开头的this为that
[root@localhost ~]# sed 's/^this/that/' Sed.txt
that is line 1,this is First line
that is line 2,the Second line,Empty line followed

that is line 4,this is Third line
that is line 5,this is Fifth line

字符转换

使用y命令可进行字符转换,其作用为将一系列字符逐个地变换为另外一系列字符,基本用法如下:

#该命令会将file中的O转换为N、L转换为E、D转换为W
#注意转换字符和被转换字符的长度要相等,否则sed无法执行
sed  'y/OLD/NEW/' file

下面的命令演示了将数字1转换为A,2转换为B,4转换为C,5转换成D的用法。

[root@localhost ~]# sed 'y/1245/ABCD/' Sed.txt
this is line A,this is First line
this is line B,the Second line,Empty line followed
this is line C,this is Third line
this is line D,this is Fifth line

插入文本

使用i或a命令插入文本,其中i代表在匹配行之前插入,而a代表在匹配行之后插入,示例如下:

#使用i在第二行前插入文本
[root@localhost ~]# sed '2 i Insert' Sed.txt
this is line 1,this is First line
Insert
this is line 2,the Second line,Empty line followed

this is line 4,this is Third line
this is line 5,this is Fifth line

#使用a在第二行后插入文本
[root@localhost ~]# sed '2 a Insert' Sed.txt
this is line 1,this is First line
this is line 2,the Second line,Empty line followed
Insert

this is line 4,this is Third line
this is line 5,this is Fifth line

#在匹配行的上一行插入问题
[root@localhost ~]# sed '/Second/i\Insert' Sed.txt
this is line 1,this is First line
Insert
this is line 2,the Second line,Empty line followed

this is line 4,this is Third line
this is line 5,this is Fifth line

读入文本

使用r命令可从其他文件中读取文本,并插入匹配行之后,示例如下:

#将/etc/passwd中的内容读出放到Sed.txt空行之后
[root@localhost ~]# sed  '/^$/r /etc/passwd' Sed.txt
this is line 1,this is First line
this is line 2,the Second line,Empty line followed

root:x:0:0:root:/root:/bin/bash
......(略去内容)......
apache:x:48:48:Apache:/var/www:/sbin/nologin
this is line 4,this is Third line
this is line 5,this is Fifth line

打印

使用p命令可进行打印,这里使用sed命令时一定要加-n参数,表示不打印没关系的行。从之前的例子中可以看出,由于sed的工作原理是基于行的,因此每次都有大量的输出。可是这些输出中有一些是我们并不需要看到的,而只需要输出匹配的行或者处理过的行就好了。简单来说,打印操作是删除操作的“逆操作”。下面使用演示来具体说明:

#打印出文件中指定的行
[root@localhost ~]# sed-n '1p' Sed.txt
this is line 1,this is First line

#将the替换成THE
#sed实际处理了第二行,其他几行由于没有匹配所以并未真正处理
#但是sed的工作原理是基于流的,所以所有流过的行都打印出来了
[root@localhost ~]# sed 's/the/THE/' Sed.txt
this is line 1,this is First line
this is line 2,THE Second line,Empty line followed

this is line 4,this is Third line
this is line 5,this is Fifth line

#使用p命令,则只打印实际处理过的行,简化了输出(使用-n参数)
[root@localhost ~]# sed-n 's/the/THE/p' Sed.txt
this is line 2,THE Second line,Empty line followed

写文件

正如之前所说,sed本身默认并不改写原文件,而只是对缓冲区的文本做了修改并输出到屏幕。所以想保存文件,除了之前提到的两种方法外(使用重定向或-i参数),还可以使用w命令将结果保存到外部指定文件。示例如下:

[root@localhost ~]# sed-n '1,2 w output' Sed.txt
[root@localhost ~]#  #这里没有任何输出,因为输出被重定向到文件了
#文件output中的内容正是Sed.txt文件中前两行的内容
[root@localhost ~]# cat output
this is line 1,this is First line
this is line 2,the Second line,Empty line followed

 sed脚本

在平日的工作中,我们可能需要定期对一些文件做分析操作,这种例行的工作往往有一定“标准化”的操作,比如说先去除文件中所有的空行,然后再全部替换某些字符等,这种过程类似于生产线上程式化的流水作业。事实上,可以把这些动作静态化地写到某个文件中,然后调用sed命令并使用-f参数指定该文件,这样就可以将这一系列动作“装载”并应用于指定文件中,这无疑加快了工作效率,这种文件就是sed脚本。请观察下面的sed脚本:

#该sed脚本的作用是将全文的this改为THAT,并删除所有空行
[root@localhost ~]# cat Sed.rules
s/this/THAT/g
/^$/d

#使用-f参数指定该脚本并应用于Sed.txt
#从输出内容中可以看出执行效果
[root@localhost ~]# sed-f Sed.rules Sed.txt
THAT is line 1,THAT is First line
THAT is line 2,the Second line,Empty line followed
THAT is line 4,THAT is Third line
THAT is line 5,THAT is Fifth line

高级替换

上面介绍了几个常用的sed命令,并逐个进行了演示。但是在实践中,往往由于需求复杂而无法简单满足。这里将介绍一些不太常用的高级编辑命令供读者参考。

❏替换匹配行的下一行

想要修改匹配行的下一行的文本,就需要使用n命令了。该命令的作用在于读取匹配行的下一行,然后再用n命令后的编辑指令来处理该行。在下面的Sed.txt文件中有一行空白行,现在想将该空格行的下一行中的line改为LINE,而文本中其他部分保持不变,操作如下:

[root@localhost ~]# sed '/^$/{n;s/line/LINE/g}' Sed.txt
this is line 1,this is First line
this is line 2,the Second line,Empty line followed

this is LINE 4,this is Third LINE
this is line 5,this is Fifth line

❏将模式空间的内容放入存储空间以便于接下来的编辑

实现该功能,就要引入H/h/G/g这4个命令了,这几个命令都是用于模式空间和存储空间转换的。首先来解释一下两个新出现的词的含义。

模式空间:当前输入行的缓冲区。

存储空间:模式空间以外的一个预留缓冲区。

下面来看看H/h/G/g这4个命令的具体含义:

▪  H:将模式空间的内容追加到存储空间。

▪  h:将模式空间的内容复制到存储空间,覆盖原有存储空间。

▪  G:将存储空间的内容追加到模式空间。

▪  g:将存储空间的内容复制到模式空间。

以下是相应的示例:

#Sed2.txt文件内容
[root@localhost ~]# cat Sed2.txt
a
b
aa
bb
#实现第一行与第二行以及第三行与第四行的反转
[root@e-bai ~]# sed '/a/{h;d};/b/G' Sed2.txt
b
a
bb
aa

sed总结:

      sed命令的功能十分强大,想面面俱到地精细列举确实不太可能。事实上,由于sed本身的复杂度,以及和正则表达式的结合,使得sed命令非常难以掌握。要想更全面地了解sed建议读者系统地阅读sed的相关书籍。限于篇幅,笔者选取了在实际工作中大量使用到的功能,并做了对应的演示,希望读者能将所有示例亲自动手做一遍,一定能帮助自己提高理解。初学者在读完本章节后,可能会忘记绝大部分内容,只有靠不断使用、加深记忆才能逐渐了解和掌握。表10-1~表10-3总结了绝大部分sed的命令和作用,方便读者查询。

表10-1 sed常用的命令

sed文本处理工具-LMLPHP

表10-2 sed常用的参数

sed文本处理工具-LMLPHP

表10-3 sed常用的正则表达式匹配

sed文本处理工具-LMLPHP

 

10-07 15:22