Linux sed 详解

##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正则

##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

& 引用pattern匹配到的字符串

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 获取匹配下一行

# 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文件内容以下:

http://www.freemethod.cn

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

http://www.freemethod.cn

An empty house

http://www.freemethod.cn

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的几个命令选项

-i选项,表示直接在文件中修改

sed '1 i\#!/bin/sh' sedswap.sh

sed -i '1 i\#!/bin/sh' sedswap.sh
#对应上面2个命令看一下sedswap.sh文件就能够发现执行完第一个命令只是
#输出到标准输出,sedswap.sh文件并无修改,而第2个命令,
#没有在标准输出中输出了,而是在sedswap.sh文件就添加了。

-e选项 -e选项后面直接跟一个完整的命令

#若是一个命令的话-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是只输出匹配行,实际上是不太准确的,-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命令结合起来使用,就只是输出处理以后的结果。

-f选项 从文件中读取命令

这个选项一直没有测试正确,不少资料也只是简单说是执行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能够完成一些难以想象的事情的时候,你就会理解那些大神的思惟是如此使人惊叹。

相关文章
相关标签/搜索