shell之sed的学习总结

  sed 工具简介

      可以进行取代、删除、新增、撷取特定行等等的功能呢!

[root@linux ~]#sed [-nefr] [function ]

参数:

-n  :使用安静(silent)模式。在一般sed 的用法中,所有来自STDIN

      的数据一般都会被列出到屏幕上。但如果加上-n 参数后,则只有经过

      sed  特殊处理的那一行(或者动作)才会被列出来。

-e  :直接在指令列模式上进行sed 的动作编辑;

-f  :直接将sed 的动作写在一个档案内,-f filename 则可以执行filename 内的sed  动作;

-r  :sed 的动作支持的是延伸型正则表达式的语法。(预设是基础正则表达式语法)

-i  :直接修改读取的档案内容,而不是由屏幕输出。

动作说明:   [n1[,n2]]function

n1, n2 :不见得会存在,一般代表『选择进行动作的行数』,举例来说,如果我的动作是需要在10 到20 行之间进行的,则『10,20[动作行为] 』

function 有底下这些:

a   :新增,a 的后面可以接字符串,而这些字符串会在新的一行出现(目前的下一行)~

c   :取代,c 的后面可以接字符串,这些字符串可以取代n1,n2 之间的行!

d   :删除,因为是删除啊,所以d 后面通常不接任何咚咚;

i   :插入,i 的后面可以接字符串,而这些字符串会在新的一行出现(目前的上一行);

p   :打印,亦即将某个选择的数据印出。通常p 会与参数sed -n 一起运作~

s   :取代,可以直接进行取代的工作哩!通常这个s 的动作可以搭配正则表达式!例如1,20s/old/new/g 就是啦!

r   :   从一个文件读入

w  :  把行写入一个文件

g   :  在一行上进行全局替换

!    :  把命令应用到除了选出的行以外的其他所有的行

n    :  读下一输入行,并开始用下一个命令处理换行符,而不是用第一个命令

h    :  把模式空间内容复制到一个固定缓存  

H   :   把模式空间内容添加到一个固定缓存  

g    :   得到固定缓存里所有的禀复制到模式缓存,重写其内容  

G   :   得到固定缓存的内容并复制到模式缓存,添加到里面 

x    :   用模式空间的内容交换固定缓存的内容  

y    :   把一个字符转换成另一个(不能和整则表达式元字符一起使用)

另外我们还有提一个逗号,如第一行到第6行可以用1,6   如果想找aa到dd之间的内容可以用/aa/,/dd/就可以。此说一下用法,一边后面看出他的意思。

sed的元字符集:

^
锚定行的开始 如:/^sed/匹配所有以sed开头的行。

$
锚定行的结束 如:/sed$/匹配所有以sed结尾的行。

.
匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。

*
匹配零或多个字符 如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。

[]
匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。

[^]
匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。

\(..\)
保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。

&
保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。

\<
锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。

\>
锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。

x\{m\}
重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。

x\{m,\}
重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。

x\{m,n\}
重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。

 

注:sed不会更改更改原 文件的内容。它的工作方式是读取文件的内容,经流编辑之后,将结果输出到标准输出。因此,要想保存sed的处理结果,用-i编辑或者w输出到一个文件。

事例:

我们用的事例用的文件是./passwd里的内容

我们先看一下前四行的内容:

[root@fei ~]# sed -n '1,4p' ./passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

删除:d

1.删除第二行,其他的显示出来

[root@fei ~]# sed '2d' passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

2.删除第2行到第4行的内容,其他的显示出来

[root@fei ~]# sed '2,4d' passwd
root:x:0:0:root:/root:/bin/bash

3.把含有daemon的行删除,其他的显示出来:

[root@fei ~]# sed '/daemon/d' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

4.把不含有nologin的行删除

[root@fei ~]# sed '/nologin/!d' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

注:因为root不含有nologin所以删除了,注意!的用法。

5.把含有空格的删除,当然上面的文本不含有空格,所以下面的用法只是所以用法

sed '/^$/d' passwd

6.删除含有3个数字的行

我们先把文本改一下,增加几个数字

[root@fei ~]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

我们把有连续有3个数字的行删除

[root@fei ~]# sed '/[0-9]\{3\}/d' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

这样daemon那一行就删除了。

注:\{n\}的用法就是重复几次如:

       \{3\} 正好重复3次

       \{3,\} 至少3次

       \{3,6\} 重复3次到6次之间

打印:p n

1.默认打印所有行,匹配的行重复打印

[root@fei ~]# sed '/root/p' passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

看到上面的root行重复打印一下

2.和-n一起使用,禁止默认打印,只打印匹配行

[root@fei ~]# sed -n '/^root/p' passwd
root:x:0:0:root:/root:/bin/bash

替换:s

1.替换root为fantefei

[root@fei ~]# sed -n 's/root/fantefei/p' passwd
fantefei:x:0:0:root:/root:/bin/bash

我们看到只是替换了第一个root为fantefei,而后面的没有替换,要是全局替换要添加g

[root@fei ~]# sed -n 's/root/fantefei/gp' passwd
fantefei:x:0:0:fantefei:/fantefei:/bin/bash

这样就全替换过来了

2.删除每行开头的前两个字母

[root@fei ~]# sed 's/^..//g' passwd
ot:x:0:0:root:/root:/bin/bash
n:x:1:1:bin:/bin:/sbin/nologin
emon:x:2:2:456daemon:/sbin:/sbin/nologin
m:x:3:4:adm:/var/adm:/sbin/nologin

s/^..//g中^是开头  ..代表两个字符

3.删除每行末的两个字母

[root@fei ~]# sed 's/..$//g' passwd
root:x:0:0:root:/root:/bin/ba
bin:x:1:1:bin:/bin:/sbin/nolog
daemon:x:2:2:456daemon:/sbin:/sbin/nolog
adm:x:3:4:adm:/var/adm:/sbin/nolog

注意要加g啊,要不至替换第一行

4.把第2行到第4行的nologin全换成bash

[root@fei ~]# sed '2,4s/nologin/bash/g' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/bash
daemon:x:2:2:456daemon:/sbin:/sbin/bash
adm:x:3:4:adm:/var/adm:/sbin/bash

5.把字符root到daemon之间的nologin全部换成bash

[root@fei ~]# sed '/root/,/daemon/s/nologin/bash/g' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/bash
daemon:x:2:2:456daemon:/sbin:/sbin/bash
adm:x:3:4:adm:/var/adm:/sbin/nologin

我们看到最后一行的没有替换,这就是/root/,/daemon/的效果

6.把开头root中的ot变成fantefei

[root@fei ~]# sed 's/^\(ro\)ot/\1fantefei/' passwd
rofantefei:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

注:s/^\(ro\)ot/\1fantefei/中\(ro\)被保留为\1使用。这就是\(\)的用法

7.在有3个连续数字的后添加.5

[root@fei ~]# sed 's/[0-9]\{3\}/&.5/' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456.5daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

看到456已经变为456.5了

这里是&的用法,保留匹配行

8.把匹配daemon的行中的nologin变为aa

[root@fei ~]# sed '/daemon/s/nologin/aa/' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/aa
adm:x:3:4:adm:/var/adm:/sbin/nologin

9.s后面不一定一定要/作为分隔符,可以用相同的两个符号作为分割符,因为有时候可以去改变/开头的文字如下面,这样就可能引起错误:

我们把root行的/bin/替换为aa

[root@fei ~]# sed '/^root/s#/bin/#aa#' passwd
root:x:0:0:root:/root:aabash

这里我们用了#作为分隔符,有效的避免了和/bin/中的/冲突

10.多次编辑用-e选项

我们把1到3行删除,然后替换其他的nologin为bash

[root@fei ~]# sed -e '1,3d' -e's/nologin/bash/' passwd
adm:x:3:4:adm:/var/adm:/sbin/bash

从文件读取:r

r命令从文本读取内容,然后输出到匹配的行后面,如果不只一个匹配行那将在每个匹配行后面输出内容

1.我们有个a的文件,里面的内容为

[root@fei ~]# cat a
loveable

我们要在root的行后输出a的文本内容

[root@fei ~]# sed '/root/r a' passwd
root:x:0:0:root:/root:/bin/bash
loveable
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

如果我们要在nologin后面输出呢,看一下:

[root@fei ~]# sed '/nologin/r a' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
loveable
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
loveable
adm:x:3:4:adm:/var/adm:/sbin/nologin
loveable

这样每个匹配的nologin都有a的内容了

写入文件内容:w

w把匹配的行写入到b的文件

[root@fei ~]# sed '/root/w b' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@fei ~]# cat b
root:x:0:0:root:/root:/bin/bash
[root@fei ~]#

添加命令:a i

1.在root后添加一行------>fantefei<--------

[root@fei ~]# sed '/^root/a ------>fantefei<---------' passwd
root:x:0:0:root:/root:/bin/bash
------>fantefei<---------
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

2.添加两行------>fantefei<--------

[root@fei ~]# sed '/^root/a \
> ------>fantefei<-------\
> ------>fantefei<-------' passwd

root:x:0:0:root:/root:/bin/bash
------>fantefei<-------
------>fantefei<-------
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

注意两行以上要加\

3.在root前添加一行------>fantefei<--------------

[root@fei ~]# sed '/^root/i -------->fantefei<------------' passwd
-------->fantefei<------------
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

4.我们向passwd文件里在末尾添加一行root,想让sed的操作写入文件需要加-i的选项

[root@fei ~]# sed -i '/adm/a root' passwd
[root@fei ~]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root

用a或者i的时候如果有多个匹配项则在每个匹配项都添加

[root@fei ~]# sed '/^root/a ---fantefei---' passwd
root:x:0:0:root:/root:/bin/bash
---fantefei---
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root
---fantefei---

看到第一行和最后一行都有添加

5.n下一个行

我们找到root开头的第一行然后在他的下一行把nologin变为bash

[root@fei ~]# sed '/^root/{n;s/nologin/bash/;}' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/bash
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root

看到root的下一行是bin,那nologin变为了bash,{n;s/nologin/bash/;} 多个命令用{}阔起来,每个命令用;分开。

替换:c

把2到3行替换为no2-3

[root@fei ~]# sed '2,3c no2-3' passwd
root:x:0:0:root:/root:/bin/bash
no2-3
adm:x:3:4:adm:/var/adm:/sbin/nologin
root

保存和取得:h和G

我们有一个文件d,里面的内容是:

[root@fei ~]# cat d
1 1
2
3
4
5
6
1 2
7
8

我们要把含有1的复制到最后一行

[root@fei ~]# sed -e '/1/h' -e '$G' d
1 1
2
3
4
5
6
1 2
7
8
1 2

我们看到d文件里有2个1开头的,一个是1 1 一个是1 2,但是sed从上往下读所以最后把1 2放到了模式空间(所以实际工作环境要使用h的时候要要这一行唯一的字符),最后在$最后一行用G提取出来

解释:当 sed 处理文件时,每行都存在模式空间(pattern space)的临时缓存中。 
  除非行被禁止打印或删除,否则行将在处理完后被打印到屏幕,然后请模式空间并把 下一输入行保存在那里等待处理。在这个例子中,在找到模式之后,把它放在模式 空间里,而且 h 命令复制它并把它存到另一个叫做保存缓存(holding buffer)中。 
第二个 sed 指令里,当读入最后一行($)时,G 命令告诉 sed 从包存缓存中取得该行 
并放回模式空间缓存,添加到当前存在那里的行中。本例子就是最后一行。

我们也可以把含有一个1的找到删除然后放到8行后

[root@fei ~]# sed -e '/1/{h;d;}' -e '8G' d
2
3
4
5
6
7
1 2
8

这时候发现第一个1都被删除了,然后从上往下匹配所以也给删除了

G和 g 的区别 
    G 命令在符合的条件行后面添加保存缓存中的内容;g 命令用保存缓存中的内容覆盖符合条件的行

如我们用g把第八行给覆盖掉

[root@fei ~]# sed -e '/1/{h;d;}' -e '8g' d
2
3
4
5
6
1 2
8

sed 命令的花括号{}的作用  
 花括号{}中可以放入多个命令,每个命令后面要用分号;

-f的使用

sed 命令表(script)是文件里的一个 sed 命令列表。用-f 选项来引用一 个命令表文件。编辑 sed 命令表有特殊要求:命令末尾不能有任何为空的空 白符或者文本。如果命令不是自成一行,就必须用分号结束。在源代码 chap4 目录下有两个编辑好的命令表文件(sedding1和 sedding2)可以参考。下面是 使用 sed命令表的例子。 

我们把sed的命令写入f的文件

 我们看一下f里的内容,注意格式

/root/a \
--------fantefei--------\
--------wokao--------------

然后我们执行一下:

[root@fei ~]# sed -f f passwd
root:x:0:0:root:/root:/bin/bash
--------fantefei--------
--------wokao--------------
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:456daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root
--------fantefei--------
--------wokao--------------

我们再看一下具体的例子:

我们有个q的文件,内容是:

hello everyone!
next please Fan Tefei speak!
welcome!

要求

1.在第一行上添加本地时间2012-9-4 9:22

2.把Fan Tefei 姓和氏互换

3.在最后添加一行THE END

那执行文件书写如下:

1i \
  TIME is 2012-9-4 9:22
s/\([A-Z][a-z]*\) \([A-Z][a-z]*\) /\2 \1/
$a \
       THE END

注:1i就是第一行上添加    $a就是最后一行添加

执行如下:

[root@fei ~]# sed -f f q
  TIME is 2012-9-4 9:22
hello everyone!
next please Tefei Fan speak!
welcome!
       THE END

你可能感兴趣的:(shell,sed)