##sed简介 sed命令说简单也简单,说复杂也复杂,看你怎么用。若是只是简单的使用的话知道s,a,i,d命令就能够了。若是要深刻一点的了解的话就要理清楚sed的处理流程,知道什么是pattern space,知道什么是hold space,它们的做用是什么。 对于sed命令刚刚开始感受很乱,傻傻分不清楚位置匹配命令。这里有一个小的技巧,发现对于sed命令有一个比较明显的特色,就是大多数的模式都是先匹配位置在执行命令。这个须要在使用过程当中多注意,慢慢的就会发现基本上均可以替换为这中模式。正则表达式
###pattern space(模式空间) 与 hold space(持有空间) pattern space能够看作是sed读取行存放和处理的内存空间,sed是按行来处理数据的,sed每从输入流中读取一行就存放在pattern space中,而后进行处理,处理后的结果也存放中pattern space中,而后在读取下一行进行处理,在读取下一行以前会先清楚pattern space,有时候咱们须要pattern space处理结果后面用怎么办呢,由于pattern space每一次读取新行以前都会清空,因此不能缓存结果,为了解决这个问题,sed就另外申请了一个空间,这个空间就是hold space,咱们能够把pattern space中的处理结果存放在hold space中。shell
###sed处理流程 数据库
###sed命令与匹配概览 编程
##sed基本命令 sed命令主要用来处理文件,若是把文件当作数据库的话,sed命令完成的操做基本上也就是增删改查,查询比较少,查询主要是为了修改。若是只是查询的话能够考虑grep。缓存
###删除app
#删除 sed '2d' fileName #删除fileName文件的第二行。 sed '2,$d' fileName #删除fileName文件的第二行到末尾全部行。 sed '$d' fileName #删除fileName文件的最后一行。 sed '/^love/d' fileName #删除fileName文件全部以love开始的行。
对于删除须要注意的是删除的匹配到的整行,而不是删除的匹配,例如sed '/love/d' fileName 就是删除fileName中包含love的全部行,而不是只是删除love。编程语言
###替换ide
#替换 sed '1,10y/abc/ABC/' fileName #将1到10行中的abc替换为ABC sed '1,10s/abc/ABC/' fileName #将1到10行中的abc替换为ABC #对于s命令更加常见的是没有位置的 #将fileName中每一行的第一个pattern(可使用正则)替换为expect sed 's/pattern/expect/' fileName #若是要所有替换可使用g(sed中有2个g一个是表示全局,一个表示从 #hold space 去数据到pattern space,这里和多数其它正则表达式同样表示全局) sed 's/pattern/expect/g' fileName #对于替换除了y,s还有一个c命令,通常用法是c\ sed '1 c\sed c change' fileName #把fileName中的第一行有sed c change替换 #对于替换命令y 和 s的区别在于y是以单个字符为单位进行替换,s是以总体进行替换 echo "abc------a-b-c" | sed 'y/abc/xyz/' #结果:xyz------x-y-z echo "abc------a-b-c" | sed 's/abc/xyz/' #结果:xyz------a-b-c
###添加测试
#给sedswap.sh文件的第一行加上#!/bin/sh sed '1 i\#!/bin/sh' sedswap.sh #在匹配到xxx行的前面一行插入Hello world sed '/xxx/i\Hello World' fileName #在匹配到xxx行的后面面一行插入Hello world sed '/xxx/a\Hello World' fileName
##sed命令拾遗spa
sed -e 's/pattern/& expect/' fileName echo "aaaHellobbb" | sed 's/Hello/ & World /' #结果:aaa Hello World bbb
sed -e 's/a/b/3' fileName #把第3个a替换为b echo "aaaabbbb" | sed 's/a/x/3' #结果:aaxabbbb
#删除不包含127.0.0.1的行 sed -e '/127.0.0.1/!d' fileName
# n 读取下一行,这种在上一行是标签,下一行是变量的时候比较经常使用 #由于没有办法匹配变量,因此匹配标签,而后提取匹配到的下一行,例如 #username: #xxxx #由于姓名xxx不是固定的,很差匹配,直接匹配username:而后找下一行接容易多了 sed '/username:/n' -e 'p' fileName
###使用其它分隔符
#使用其它分隔符 #表示把全部Hello替换成Hello World。 sed 's#Hello#Hello World#g' fileName #不论什么字符,紧跟着s命令的都被认为是新的分隔符。 #因此,“#”在这里是分隔符,代替了默认的“/”分隔符。
###使用()分组
#使用()分组 #思考:怎样把aaatestbbb中的test提取出来呢?注意不是替换或者删除, #是获取,而且保存到hold space 以便于使用,这里就能够是用() #像其它正则表达式同样,sed也可使用()进行分组 #这里咱们利用分组来保存匹配,而后使用替换来把分组中的内容放到pattern space中 #而后使用h把pattern space中的内容拷贝到hold space中 echo "aaatestbbb" | sed 's/aaa\(test\)bbb/\1/' #一个()就表示一个分组,\1表示的第一分组,依次类推第二个分组\2,第三个分组\3 ··· #更加通常的表示 echo "aaatestbbb" | sed 's/.*\(test\).*/\1/' #放到hold space中 echo "aaatestbbb" | sed 's/.*\(test\).*/\1/;h;g'
###使用x交换pattern space 与 hold space 与pattern space 与 hold space存取相关的主要有4个命令,分别是g,G,h,H。能够把g看作是get的嘛,就是用hold space中覆盖pattern space。G是吧hold space中的内容追加到pattern space中。同理,h能够看作是hold,表示用pattern space中的内容覆盖hold space中。H表示把pattern space中的内容追加到hold space中。
#让World Hello位置互换 echo "World Hello" | sed '/World/h;s/\(World\).*/\1/;x;s/.*\(Hello\)/\1/;G;s/\n/ /' #固然上面那个比较复杂了,下面来一个简单的 echo "World Hello" | sed 's/\(World\)\(Hello\)/\2 \1/'
###使用r 和 w命令 r是读文件的意思,在sed中就表示从文件中读取内容插入到匹配行以后。仍是来一个具体的例子来讲一下吧。好比有一个adv文件内容以下:
mylove文件内容以下:
an empty street
An empty house
A hole inside my heart
I'm all alone\n The rooms are getting smaller
I wonder how
I wonder why
执行下面的命令:
sed '/empty/r adv' mylove
结果以下:
an empty street
An empty house
A hole inside my heart
I'm all alone
The rooms are getting smaller
I wonder how
I wonder why
咱们能够发现实在匹配到empty的行的后一行加了adv文件中的内容,咱们并无使用a命令。
w命令就是写命令,在sed就是把匹配到的行写入指定的文件中,咱们仍是使用上面的mylove文件,执行下面的命令:
sed '/empty/w result' mylove
执行完result文件中的内容为:
an empty street
An empty house
咱们能够看到把匹配到的2行写入到了result文件中。
##sed的几个命令选项
sed '1 i\#!/bin/sh' sedswap.sh sed -i '1 i\#!/bin/sh' sedswap.sh #对应上面2个命令看一下sedswap.sh文件就能够发现执行完第一个命令只是 #输出到标准输出,sedswap.sh文件并无修改,而第2个命令, #没有在标准输出中输出了,而是在sedswap.sh文件就添加了。
#若是一个命令的话-e能够省略,例以下面2个命令就是同样同样的 sed '/xxx/a\Hello World' fileName sed -e '/xxx/a\Hello World' fileName #多个命令的话就要在每一命令前面都加上-e参数或者使用;分割 sed -e '/xxx/i\Hello World' -e '/xxx/a\Hello World' fileName #sed '/xxx/i\Hello World; /xxx/a\Hello World' fileName
这里有一个误区,不少资料说-n是只输出匹配行,实际上是不太准确的,-n就是不输出,包括匹配到的都不输出。能够经过一个例子来验证一下,假设num文件中的内容为:
111111111
222222222
333333333
444444444
555555555
sed 's/333/xxx/' num #结果以下:
111111111
222222222
xxx333333
444444444
555555555
sed -n 's/333/xxx/' num #是没有输出的 sed -n 's/333/xxx/p' num #结果以下:
xxx333333
sed 's/333/xxx/p' num #结果以下:
111111111
222222222
xxx333333
xxx333333
444444444
555555555
从上面的结果来看,咱们能够总结处理-n是不输出,p(小p)是输出匹配(sed处理的行),因此通常咱们-n参数和p命令结合起来使用,就只是输出处理以后的结果。
这个选项一直没有测试正确,不少资料也只是简单说是执行sed脚本。其实这个命令是从指定的文件中读取命令,不是脚本,只是sed命令,例如咱们要执行命令
sed 's/333/xxx/p' num
先在只须要把s/333/xxx/p写入到一个文件中,这里假设是command文件,接下来只须要执行下面的命令就能够了:
sed -f command num
注意:文件中每一行是一个命令,命令不要加引号。 下面来一个更加具体的例子来讲明一下,假设有一个文件word中的内容以下:
we have joy fun
we have joy in the sun
hello my trusted friend
command中的内容以下:
s/have/had/
a\append in the end
s/joy/joying/
执行下面的命令:
sed -f command word
结果以下:
we had joying fun
append in the end
we had joying in the sun
append in the end
hello my trusted friend
append in the end
##sed小结 注意sed是以行为单位做为处理和结果输出的,你能够把sed看作是一个简单的编程语言,它按行来处理脚本。它可使用一个主内存pattern space和一个寄存器hold space。当你发现sed能够完成一些难以想象的事情的时候,你就会理解那些大神的思惟是如此使人惊叹。