Sed 的基本用法
1、sed介绍及工作流程:
很多时候我们在linux下面都需要编辑一些文件。我们所使用的编辑器一般都是vi/vim。Vim属于屏幕编辑器,所谓屏幕编辑器是说,我们编辑一个文件的时候,需要把这个文件打开,这样存在两个问题:1、因为我们需要打开文件,所以如果说一个比较大的文件,将会消耗很多内存;2、当我们编辑文件的时候,必须要互动,这样的话,如果我们在写脚本的时候,是很难调用Vim。这个时候就需要使用其他的编辑器,sed就是其中的一种。
Sed属于流编辑器,所谓的流编辑器是这样的,sed在编辑文件的时候,首先会把文件的一行内容读入内存,然后根据我们的需要来进行编辑。读入内存的这部分,我们称作是模式空间,修改完,会把模式空间的内容输出到屏幕,然后把模式空间的内容清空。读取下一行到模式空间。这样的话就避免了一次性读取整个文件。
2、sed的基本命令:
sed的语法:
sed ‘范围 操作命令’ file
如果范围没有指定的话,那么将会对全文每行进行操作。
有时候我们需要指定操作范围,指定范围的方法有两种:第一种是直接写一个数字,表示对多少行进行操作:
注:首先介绍一个命令d,表示删除
上图表示删除cc文件的第二行。
上图表示删除cc文件的最后一行。
第二种是指明范围的方式是正则表达式,如果我们使用正则表达式来表示范围的话,必须使用//隔开,比如:
上图表示删除以root开头的行。
以上是对单行操作的,我们也可以对多行操作:
上图表示删除第一行到第四行。除了使用数字表示范围之外,还可以:
上图表示删除包含root的行到第一次包含sync的行之间的所有行。
以上是所说的范围,如果没有指定范围的话,将对全文进行操作。
还有其他命令:
S 表示替代的意思:
Sed ‘范围 s/老字符/新字符/标记’ file
(在这里老字符部分是支持正则表达式的,但是在新字符的位置是不支持正则表达式的,没有什么特殊字符,除了\n \&)
上图表示把rhce替换成RHCA。因为没有指定标记,所有只能替换每行的第一个关键字。如果要替换所有内容或其他关键字,就要使用标记:
最后加上标记g,表示对每行的所有关键字都进行替换。
如果要替换每行的第二个关键字,可以用以下方式:
同理替换第n个关键字,即加上数字n。
上图表示替换第二个到最后一个关键字。
上图表示指定范围为第一行,并替换第二个关键字(:号替换为--)。
我们在执行替换操作的时候,不一定非得使用//来隔开,可以使用其他任意字符,比如@或#等(只能在s操作时有效):
& 替换字符部分是有意义,代表的意思是前面的关键字。
刚才提到两个命令d和s,如果说我们对特定的范围做多个操作的话,那么我们需要把多个操作用{}括起来,操作之间用;隔开:
上图表示首先把第一行的所有rhce替换成RHCA,然后把第一个RHCA替换成XXXX。
Sed读取文件的一行,然后操作,操作完成之后,会把结果显示在屏幕上,如果想查看模式空间中的内容的话,可以使用p:
上图除了显示正常的内容,还特别显示了模式空间的内容。如果我们不想在屏幕输出没有编辑过的那些文件,只要给sed加上-n选项就可以:
如果要替换单个字符的话,可以使用y命令:
上图表示替换第一行,字母c替换为字母z。(如果第一行有a和b的话,也分别替换为x和y)。
还有其他一些简单的命令:
a\ 表示追加,在关键词后面一行加上一行内容:
上图表示在DEVICE这行的下面一行添加一行XXXXXXXX内容。
i\ 表示在关键词的上一行追加一行内容:
修改某行内容可以使用/c命令:
注意:以上我们所做的所有操作都是在模式空间里面做的(内存里面操作),并没有改变源文件的内容。
如果要改变源文件,只要对sed命令加上-i选项就可以了。
3、sed其他常见命令
“=”代表显示匹配到行的行号
n: 读取下一行。前面讲到:Sed会把一行内容读取到模式空间,然后用后面的命令来操作,操作完成之后,会把模式空间里面的内容显示在屏幕上,然后把模式空间里面的内容删除,同时把下一行内容读取到模式空间。
但有时候,我们需要匹配一行之后,然后对匹配行的下一行来进行操作:
如上图所示,首先匹配到开头是zz的这一行,匹配之后sed会把当前模式空间里面的内容(zz开头的那行)删除,然后读取下一行内容,然后利用n后面的命令对当前模式空间内容操作,即把tom替换为TOM。
以上命令是把所有的rhce全部换成RHCE。但是我们看到第一行的最后有rh,第二行的开头有ce,因为这个rhce被分成了两行,所以刚才的那个命令就没有把这个分开rhce换成RHCE。如果我们现在想把这分成两行的rhce也换成RHCE的话,就需要使用N,N的意思是多行模式空间。意思就说,当sed读取第一行的时候,遇到了N,然后就会把下一行的内容读取到模式空间,而原来模式空间里面的内容是不删除的,只是把新的一行内容附加到模式空间。
上面的命令只是替换行末的rh和第二行的ce,变为RHCE。
其他的rhce是没有改变的。
我们可以这样完成,如下图所示:
如果我们使用多行模式空间的话,^就不表示行的开头,而是模式空间的开头,$就不表示行尾,而是模式空间的结束。
文件aaa内容如上图:
如上图所示,替换仅仅是模式空间里的开头的rhce,而并不是每行的开头。下图所示,是每行的开头:
$表示模式空间的结尾,而不是文件中每行的结尾。如下图所示:
除了模式空间之外,还有保持空间,我们可以理解是一个缓存。
当我们对模式空间里面的内容操作的时候,如果相对模式空间里面的内容保存一个副本的话,那么我们可以把模式空间里面的内容存储在保持空间里面。保持空间的内容和模式空间的内容是可以互换的。使用命令式h(H)、g(G),h(H)是把模式空间的内容存储到保持空间,g(G)的意思是把保持空间的内容存储在模式空间里面。
文件bbb内容如下图:
现在想把文件bbb里面的内容变成如下格式:
b
a
bb
aa
我们可以这么完成:
上面就是一些常见的命令。
当我们在学习其他语言的时候,经常会遇到循环,我可以让满足某些条件的内容重新执行某些命令,比如我们可以是while循环等等,但是在sed里面没有这些。如果我们也想执行一些循环的话,可以借助标签来完成:
语法:sed ‘:label; 命令1;命令2;…;/模式/b label’ file
使用:后面跟上一些字符来定义一个标签,然后会把file第一行的内容读取到模式空间,然后命令1,命令2……直到命令n来操作,如果模式匹配的话,那么模式空间里面的内容会重复执行label后面的命令,也就是命令1,命令2……直到命令n。
转载于:https://blog.51cto.com/pancho/1539287