Sed 的基本用法

1、sed介绍及工作流程:

很多时候我们在linux下面都需要编辑一些文件。我们所使用的编辑器一般都是vi/vimVim属于屏幕编辑器,所谓屏幕编辑器是说,我们编辑一个文件的时候,需要把这个文件打开,这样存在两个问题:1、因为我们需要打开文件,所以如果说一个比较大的文件,将会消耗很多内存;2、当我们编辑文件的时候,必须要互动,这样的话,如果我们在写脚本的时候,是很难调用Vim。这个时候就需要使用其他的编辑器,sed就是其中的一种。

 

Sed属于流编辑器,所谓的流编辑器是这样的,sed在编辑文件的时候,首先会把文件的一行内容读入内存,然后根据我们的需要来进行编辑。读入内存的这部分,我们称作是模式空间,修改完,会把模式空间的内容输出到屏幕,然后把模式空间的内容清空。读取下一行到模式空间。这样的话就避免了一次性读取整个文件。


2、sed的基本命令:

sed的语法:

sed ‘范围 操作命令’ file

如果范围没有指定的话,那么将会对全文每行进行操作。

有时候我们需要指定操作范围,指定范围的方法有两种:第一种是直接写一个数字,表示对多少行进行操作:

注:首先介绍一个命令d,表示删除

wKiom1Pq1OrCZWk1AAHzkJHX6m8359.jpg

上图表示删除cc文件的第二行。

wKiom1Pq1TvD9TTCAAEIHOonSIM883.jpg

上图表示删除cc文件的最后一行。

 

第二种是指明范围的方式是正则表达式,如果我们使用正则表达式来表示范围的话,必须使用//隔开,比如:

wKioL1Pq1mazQ0D3AAFAbAzExZE733.jpg

上图表示删除以root开头的行。

 

以上是对单行操作的,我们也可以对多行操作:

wKioL1Pq1n2wCoRiAACsJdSlGRE705.jpg

上图表示删除第一行到第四行。除了使用数字表示范围之外,还可以:

wKiom1Pq1X-hBIwBAACZZE8Uw50925.jpg

上图表示删除包含root的行到第一次包含sync的行之间的所有行。

以上是所说的范围,如果没有指定范围的话,将对全文进行操作。

 

还有其他命令:

S 表示替代的意思:

Sed ‘范围 s/老字符/新字符/标记’ file

(在这里老字符部分是支持正则表达式的,但是在新字符的位置是不支持正则表达式的,没有什么特殊字符,除了\n \&

 

wKioL1Pq1rXxUD2QAACyQP6d9Uo120.jpg

上图表示把rhce替换成RHCA。因为没有指定标记,所有只能替换每行的第一个关键字。如果要替换所有内容或其他关键字,就要使用标记:

wKiom1Pq1bnDMQXoAABqIQcHu6I335.jpg

最后加上标记g,表示对每行的所有关键字都进行替换。

如果要替换每行的第二个关键字,可以用以下方式:

wKiom1Pq1criNDXyAABOZlc4iRQ226.jpg

同理替换第n个关键字,即加上数字n

 

wKioL1Pq1vGQcsUCAABttkTcrjo907.jpg

上图表示替换第二个到最后一个关键字。

 

wKioL1Pq1wTTPpihAAEnLrFtHXM842.jpg

上图表示指定范围为第一行,并替换第二个关键字(:号替换为--)。

 

我们在执行替换操作的时候,不一定非得使用//来隔开,可以使用其他任意字符,比如@#等(只能在s操作时有效):

wKiom1Pq1fqTWoe_AAFkfhbE5sk911.jpg

 

& 替换字符部分是有意义,代表的意思是前面的关键字。

wKioL1Pq1yCxR-CzAABeqtB5rNI139.jpg

 

刚才提到两个命令ds,如果说我们对特定的范围做多个操作的话,那么我们需要把多个操作用{}括起来,操作之间用;隔开:

wKiom1Pq1huSZEdAAAB0qjAvlHQ331.jpg

上图表示首先把第一行的所有rhce替换成RHCA,然后把第一个RHCA替换成XXXX

 

Sed读取文件的一行,然后操作,操作完成之后,会把结果显示在屏幕上,如果想查看模式空间中的内容的话,可以使用p

wKioL1Pq11LC_uqYAAB2F6wqZPM083.jpg

上图除了显示正常的内容,还特别显示了模式空间的内容。如果我们不想在屏幕输出没有编辑过的那些文件,只要给sed加上-n选项就可以:

wKiom1Pq1k7whkVSAABqSiqqZcU535.jpg

 

如果要替换单个字符的话,可以使用y命令:

wKioL1Pq13fjYRZgAABUeCJMi6I425.jpg

上图表示替换第一行,字母c替换为字母z(如果第一行有ab的话,也分别替换为xy)

 

还有其他一些简单的命令:

a\ 表示追加,在关键词后面一行加上一行内容:

wKiom1Pq1m2S-ea2AAEHMs_yuUM169.jpg

上图表示在DEVICE这行的下面一行添加一行XXXXXXXX内容。

 

i\ 表示在关键词的上一行追加一行内容:

wKioL1Pq15WAfmBVAADAhx1rdhk898.jpg

修改某行内容可以使用/c命令:

wKioL1Pq16CgkjEiAAFJot0ZIcI753.jpg

 

注意:以上我们所做的所有操作都是在模式空间里面做的(内存里面操作),并没有改变源文件的内容。

 

如果要改变源文件,只要对sed命令加上-i选项就可以了。

wKioL1Pq17Kj4s6PAADGzbtDi_0172.jpg


3、sed其他常见命令

=代表显示匹配到行的行号

wKiom1Pq1qjR8Dn8AACb1m-enJw536.jpg

 

n: 读取下一行。前面讲到:Sed会把一行内容读取到模式空间,然后用后面的命令来操作,操作完成之后,会把模式空间里面的内容显示在屏幕上,然后把模式空间里面的内容删除,同时把下一行内容读取到模式空间。

但有时候,我们需要匹配一行之后,然后对匹配行的下一行来进行操作:

wKioL1Pq2EfxpUZDAAC0MCn4E1g548.jpg

如上图所示,首先匹配到开头是zz的这一行,匹配之后sed会把当前模式空间里面的内容(zz开头的那行)删除,然后读取下一行内容,然后利用n后面的命令对当前模式空间内容操作,即把tom替换为TOM

 

wKioL1Pq2FWg4uRJAACYWVdh3M4898.jpg

以上命令是把所有的rhce全部换成RHCE。但是我们看到第一行的最后有rh,第二行的开头有ce,因为这个rhce被分成了两行,所以刚才的那个命令就没有把这个分开rhce换成RHCE。如果我们现在想把这分成两行的rhce也换成RHCE的话,就需要使用NN的意思是多行模式空间。意思就说,当sed读取第一行的时候,遇到了N,然后就会把下一行的内容读取到模式空间,而原来模式空间里面的内容是不删除的,只是把新的一行内容附加到模式空间。

wKiom1Pq10qDoX2iAADqON9Ap1E098.jpg

上面的命令只是替换行末的rh和第二行的ce,变为RHCE

其他的rhce是没有改变的。

我们可以这样完成,如下图所示:

wKioL1Pq2G_BA9hqAACRde6pInk788.jpg

 

如果我们使用多行模式空间的话,^就不表示行的开头,而是模式空间的开头,$就不表示行尾,而是模式空间的结束。

wKioL1Pq2HyiV-Y7AABDjpqFzOI453.jpg

文件aaa内容如上图:

 

wKiom1Pq13Czf1pKAABipDaFG0A055.jpg

如上图所示,替换仅仅是模式空间里的开头的rhce,而并不是每行的开头。下图所示,是每行的开头:

wKioL1Pq2JWjaBDCAABNiXNdG1Y916.jpg

 

$表示模式空间的结尾,而不是文件中每行的结尾。如下图所示:

wKiom1Pq14fg6zlwAAByq502Ucw219.jpg

 

除了模式空间之外,还有保持空间,我们可以理解是一个缓存。

当我们对模式空间里面的内容操作的时候,如果相对模式空间里面的内容保存一个副本的话,那么我们可以把模式空间里面的内容存储在保持空间里面。保持空间的内容和模式空间的内容是可以互换的。使用命令式hH)、gG),hH)是把模式空间的内容存储到保持空间,gG)的意思是把保持空间的内容存储在模式空间里面。

文件bbb内容如下图:

wKioL1Pq2KviaHyoAAA3s5OyQf8637.jpg

 

现在想把文件bbb里面的内容变成如下格式:

b

a

bb

aa

 

我们可以这么完成:

wKiom1Pq16Lz_GFRAABIIuMPdio068.jpg

 

上面就是一些常见的命令。

当我们在学习其他语言的时候,经常会遇到循环,我可以让满足某些条件的内容重新执行某些命令,比如我们可以是while循环等等,但是在sed里面没有这些。如果我们也想执行一些循环的话,可以借助标签来完成:

语法:sed  ‘:label; 命令1;命令2;…;/模式/b label’  file

使用:后面跟上一些字符来定义一个标签,然后会把file第一行的内容读取到模式空间,然后命令1,命令2……直到命令n来操作,如果模式匹配的话,那么模式空间里面的内容会重复执行label后面的命令,也就是命令1,命令2……直到命令n

wKiom1Pq167SOu0MAACoNJ2WkhY991.jpg