sed 的详细用法

sed:stream editor 流编辑器
sed的工作模式;sed是一个行文本编辑器,默认每次处理文本中所匹配到一行内容到模式空间,然后用后面的命令进行操作,操作完成之后,会把模式空间
里面的内容实现在屏幕上,然后把模式空间的中的内容删除,同时把下一行所匹配到内容读入模式空间

为了下面演示方便,我们创建一个文本文件a.text

#cat a.text
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

sed 命令的语法格式:

sed [options] 'addresscommand' file (1)
sed [options] -f scriptfile file (2)

(2)是sed的脚本用法后面会介绍到
先介绍语法(1)种用法:**


address(匹配的条件)的表示法:

linenumber:指定特定行号
startline,endline:指定起始行号,和结束行号
linenumber,+N :N数字,表示从指定行号向后N行
/patten/:以正则表达式的匹配模式
/patten1/,/patten2/:从模式匹配1到模式匹配2


options:选项

-n 静默模式 常使用p命令时会用
-i 改变原文件
-f file 跟脚本文件
-e 可以执行多个命令语句


command:命令(简单用法)

p:打印模式空间中行
d:删除,删除选择的行
r file:读取file中的内容追加到匹配的行后面
R file:读取file中的内容的第一行追加到匹配行的后面
w file:将匹配到的行,保存到file中
W file:将匹配到的行的第一行,保存到file中
a \string 在当前行下面插入文本。
i \string 在当前行上面插入文本。
! 表示后面的命令对所有没有被选定的行发生作用.
y 和s用法类似,但只能替换大小写
s/patten/string/ 把patten匹配到的换成string字符


sed替换标记:

g表示全局替换
\1表示前面第一个左括号所表示的内容,\2表示前面第二个左括号中表示的内容,以此类推
&表示前面匹配到的内容


sed 元字符

^ 匹配行开始,如:/^sed/匹配所有以sed开头的行。
$ 匹配行结束,如:/sed$/匹配所有以sed结尾的行。
. 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d。

  • 匹配0个或多个字符,如:/*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结尾的单词的行。
    x{m} 重复字符x,m次,如:/0{5}/匹配包含5个0的行。
    x{m,} 重复字符x,至少m次,如:/0{5,}/匹配至少有5个0的行。
    x{m,n} 重复字符x,至少m次,不多于n次,如:/0{5,10}/匹配5~10个0的行。

下面我们看例子:

address 匹配条件的用法

1,只显示a.text中的2行

root@debian9:~# sed -n '2p' a.text 
ce xx xx tom xx rhce xx tom xx

注意,我们也里面要用到-n 选项,如果不用-n 静默模式的话,
它会显示全部内容(这是sed的默认动作,可以看一下工作模式),匹配到的内容会显示两遍

2,删除a.text 中2-4行

root@debian9:~# sed "2,4d" a.text 
zz xx tom xx tom rhce xx rh
yyyy rhce yyyyy 

3,上面删除a.text中2-4行,也可以这样表示

root@debian9:~# sed "2,+2d" a.text 
zz xx tom xx tom rhce xx rh
yyyy rhce yyyyy 

4,删除以x开头的行。

root@debian9:~# sed "/^x/d" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
yyyy rhce yyyyy 

5,删除a.text中以第一个zz开头的行到第一个xx开头的行结束。

root@debian9:~# sed "/^zz/,/^xx/d" a.text
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

command 命令的用法

1,i \string 的用法,在a.text中ce开头的行前面追加 i love linux 的新行

root@debian9:~# sed "/^ce/i \i love linux" a.text   
zz xx tom xx tom rhce xx rh
i love linux
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

2,a \string 的用法和i \string 类似 在a.text中ce开头的行后面追加i love linux 的新行

root@debian9:~# sed "/^ce/a \i love linux" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
i love linux
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

3,r file的用法,把/etc/fstab 追加到a.text中含有y的行。

root@debian9:~# sed "/.*y.*/r /etc/fstab" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 
/etc/fstab: static file system information.
           
/ was on /dev/sda1 during installation
UUID=d12e3f89-049d-45c1-8b31-3a1cf551585f /   ext4    errors 0       1
swap was on /dev/sda5 during installation
UUID=07308ec5-870b-46f0-b983-ebc2a56fb0f2 none  swap    sw   0       0
/dev/sr0  /media/cdrom0   udf,iso9660 user,noauto     0       0

4,w file 的用法,把a.text中含有tom的行,保存到/root/b.text

root@debian9:~# sed "/tom/w /root/b.text" a.text
root@debian9:~# cat b.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 

5,s/patten/string/的使用。把a.text 中第一个tom换成jerry .

root@debian9:~# sed "s/tom/jerry/" a.text 
zz xx jerry xx tom rhce xx rh
ce xx xx jerry xx rhce xx tom xx 
xx xx jerry xx rhce xx xx 
xxx xxx jerry rhce xx xx 
yyyy rhce yyyyy 

提示;sed默认只替换第一个匹配到的patten.如果想替换只替换第二tom为jerry
这时替换标记就用作用了
这条命令可以这样写:sed "s/tom/jerry/2" a.text 以此类推。可以替换想要替换的,

如果要想替换全部的可以写成
sed "s/tom/jerry/g" a.text

root@debian9:~# sed "s/tom/jerry/g" a.text
zz xx jerry xx jerry rhce xx rh
ce xx xx jerry xx rhce xx jerry xx 
xx xx jerry xx rhce xx xx 
xxx xxx jerry rhce xx xx 
yyyy rhce yyyyy

&和\1的用法,&和\1的相同之处,和不同点
把she like my love 中 like和love后面都加上一个r.变成she liker my lover

root@debian9:~# echo "she like my love" | sed "s/l..e/&r/g"
she liker my lover

注释,&表示前一个/patten/中的内容

root@debian9:~# echo "she like my love" | sed  "s/\(l..e\)/\1r/g"
she liker my lover

可以用分组的方法来实现后向引用。

如果把she like my love 中like和love中的l变成L。变成she Like my Love

root@debian9:~# echo "she like my love" | sed  "s/l\(..e\)/L\1/g"
she Like my Love

这样的只能用分组来实现。不能用&来引用。

sed的高级用法

command:命令、

=:显示行号
n:读取匹配模式的行的下一行到模式空间中.注:模式空间中匹配模式的行被删除。
N:读取匹配模式的行,和匹配模式行的下一行。
h 拷贝模板块的内容到内存中的缓冲区。如果原来缓冲区有内容被覆盖
H 追加模板块的内容到内存中的缓冲区。
g 获得内存缓冲区的内容,并替代当前模板块中的文本。
G 获得内存缓冲区的内容,并追加到当前模板块文本的后面

高级command的用法

1,= 的用法。显示以ce开头的是第几行。

root@debian:~#  sed "/^ce/=" a.text 
zz xx tom xx tom rhce xx rh
2
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

2,n 的用法。把zz开头的行,下一行中的tom全部换成TOM

root@debian:~# sed "/^zz/{n;s/tom/TOM/g}" a.text
zz xx tom xx tom rhce xx rh
ce xx xx TOM xx rhce xx TOM xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

3,N的用法,把zz开头的行和下一行中的rhce全部换成RHCA.

root@debian:~# sed "/^zz/{N;s/rhce/RHCA/g;s/rh\nce/RH\nCA/}" a.text 
zz xx tom xx tom RHCA xx RH
CA xx xx tom xx RHCA xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

首先,要用N读取zz开头的行和它的下一行,可以看到zz行的结尾处rh和ce开头的行是两行,
用s/rhce/RHCA/g不会被替换。所以我们还要s/rh\nce/RH\nCA/来替换。

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

root@debian:~# sed "/^xx/{N;s/^xx/qq/g}" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
qq xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

分析:如果不是模式空间的开头,那么下面两个xx也会被替换成qq.

h和G的用法:
我们新建一个文本b

#cat b
a
b
aa
bb

4,通过模式空间和保持空间的转化实现的效果

root@debian:~# sed "/a/{h;d};/b/G" b
b
a
bb
aa

sed [options] -f scriptfile file (2)
通常通过脚本对文件批量处理;
如一个文件中需要多出用sed 修改可以使用脚本
脚本文件格式为:'addresscommand'
'addresscommand'
......