在Linux的世界中,有着一个文本三剑客的称呼,它们分别代表grep(文本过滤),sed(流编辑器),awk(gawk)(报告生成器)。
它们是强大的文本处理工具,了解并掌握它们,可以让你对文本的处理更加从容和轻松。
今天我们主要是围绕sed来进行分析。
一、初识sed
sed:Stream Editor
从名字上也可以直观的了解到它是一个流编辑工具。何为流编辑器?就是把文本中的文字按照特定的分隔方式,进行数据流处理。sed就是基于这种方式,它是以换行符以分隔单位,对文本进行逐行的处理。
二、初识sed的工作原理
前提:首先对于一个文本文件来说,它是由至上而下的一行或N行组成。
1、当用sed命令对文本进行处理的时候,sed先读取对象的文本文件的第一行到模式空间中。
2、当有内容进入“模式空间”时,sed的编辑命令对模式空间中的内容进行编辑操作(修改,替换,删除,追加,显示等等)
3、模式空间中的内容编辑处理完成之后,sed把此内容通过标准输出(默认为显示器)打印出来,并删除模式空间中的内容。
4、第一行处理结束。从新读取第二行的内容进行处理,直到最后一行。
三、sed命令的基本语法
sed OPTIONS… [SCRIPT] [INPUTFILE…]
常用的选项:
-n,–quiet: 不输出模式空间中的内容
-i: 直接编辑原文件,默认不对原文件进行操作
-e: 可以使用多个命令(脚本)进行操作
-f /path/from/sed_script: 从指定的文本中读取处理脚本
-r: 使用扩展正则表达式
四、模式空间中的编辑操作
1、地址定界:
1)#:#为数字,指定要进行处理操作的行
2)$:表示最后一行,多个文件进行操作的时候,为最后一个文件的最后一行
3)/regexp/:表示能够被regexp匹配到的行
regexp及基于正则表达式的匹配:关于正则表达式的请参考 grep的基本用法详解中的【三、了解正则表达式】
4)/regexp/I:匹配是忽略大小写
5)\%regexp%: 任何能够被regexp匹配到的行,换用%(用其他字符也可以,如:#)为边界符号
6)addr1,addr2:指定范围内的所有的行(范围选定)
常用的以下几种表示方法:
a)0,/regexp/:从起始行开始到第一次能够被regexp匹配到的行
b)/regexp/,/regexp/:被模式匹配到的行内的所有的行
c)#,#:#为数字,给定具体的行范围
d)#,+N:#为数字,从#开始的行开始,向下N行的所有的行
7)first~step:指定起始的位置及步长,例如:1~2表示1,3,5…
2、常用的编辑命令:
1)d:删除匹配到的行
2)p:打印模式空间中的内容
注意:sed默认情况下是把“模式空间”中的内容全部进行显示,p的意义在于把匹配到的行进行显示。
所以其显示的结果是“默认的显示内容+p要显示的内容”。
因此通常与-n选项一起使用,表示只显示匹配到的行。
3)a \text:append,表示在匹配到的行之后追加内容
4)i \text:insert,表示在匹配到的行之前追加内容
5)c \text:change,表示吧匹配到的行和给定的文本进行交换
6)s/regexp/replacement/flages:查找替换,把text替换为regexp匹配到的内容(其中/可以用其他字符代替,例如@)
可能会用到的特殊replacemen(通常replacement为固定的字符窜):
\L:转换后面的内容第一个字母为小写字母
\l:后面的内容全部转换成小写,直到遇到\E为止
\U:转换后面的内容第一个字母为大写字母
\u:后面的内容全部转换成大写,直到遇到\E为止
\E:当以\L或\U开始的时候,\E意味着停止字符的转换
如果是replacement为变量时,用'$VAR'引用即可
常用的flages:
g:全局替换,默认只替换第一个
i: 不区分大小写
p:如果成功替换则打印
7) w /path/to/somefile:将匹配到的文件另存到指定的文件中
8) r /path/from/somefile:将读取指定的文件内容到匹配的行处(如果指定文件为多行时,追加到匹配行之后)
五、知识点练习
1、显示文件中的偶数行:
1)用first~step的方式来实现,把奇数行删除,自然显示的事偶数行
2)不输出默认的显示内容,用p指定显示偶数行
3、把以/sbin/nologin结尾的行的小写字母全部替换成大写
1)先用/regexp/地址定界的来选定以/sbin/nologin结尾的行#显示所有以/sbin/nologin$结尾的行# sed -n '\#/sbin/nologin$#p' test.txt
2)查找替换
查找所有的小写字符[a-z]
其中/\u&/中的&表示前面所匹配到的所有内容,所以/\u&/g为前面所匹配到的小写字母全部替换为大写字母
工作的实例一、
1. 将下面的文件的小写字母全装换为大写字母。
如下:[root@server161 myfile]# cat oldboy.txt
oldboy.blog.51cto.com
[root@server161 myfile]# sed 's/\w*/\u&\E/g' oldboy.txt
Oldboy.Blog.51cto.Com
Www.Oldboyedu.Com
[root@server161 myfile]# sed 's/[a-z]/\u&/g' oldboy.txt
OLDBOY.BLOG.51CTO.COM
WWW.OLDBOYEDU.COM
[root@server161 myfile]# sed 's/\W*/\L&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
[root@server161 myfile]# sed 's/\W*/\U&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
[root@server161 myfile]# sed 's/\W*/\U&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
You have new mail in /var/spool/mail/root
[root@server161 myfile]# sed 's/[A-Z]/\U&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
[root@server161 myfile]# sed 's/[A-Z]/\u&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
[root@server161 myfile]# sed 's/[a-z]/\U&/g' oldboy.txt
OLDBOY.BLOG.51CTO.COM
WWW.OLDBOYEDU.COM
[root@server161 myfile]# sed 's/[A-Z]/\L&/g' oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
[root@server161 myfile]# sed 's/[a-z]/\u&/g' oldboy.txt
5、用sed命令修改/tmp/sed/inittab中的id:X:initdefault:修改为id:5:initdefault:(其中X为任意的数字)
[root@server161 myfile]# cat oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
id:3:initdefault
[root@server161 myfile]# sed -i 's@\(id:\)[0-9]\(:initdefault\)@\5\2@' oldboy.txt
sed:-e 表达式 #1,字符 36:“s”命令的RHS非法引用\5
You have new mail in /var/spool/mail/root
[root@server161 myfile]# sed -i 's@\(id:\)[0-9]\(:initdefault\)@\15\2@' oldboy.txt
[root@server161 myfile]# cat oldboy.txt
oldboy.blog.51cto.com
www.oldboyedu.com
id:5:initdefault
注: 这里的@ 跟/ 的意思是一样的,但是在正则中易于好看, 后面的\1,\2 指的就是第一个捕获组和第二个捕获组,id 和initadefault 的意思。
六、sed的知识扩展
在sed的工作原理图中我们了解到,sed不仅存在模式空间,也存在一个保持空间(hold space)。顾名思义,保存空间是一段sed独有的内存空间片段,可以暂时存放一些数据。
其中与“保持空间”相关的编辑命令有:
h:把模式空间中的内容覆盖到保存空间中的内容
H:把模式空间中的内容追加到保存空间中(加在原有内容之后)
g:把保持空间中的内容覆盖到模式空间中的内容
G:把保持空间中的内容追加到模式空间中(加在原有内容之后)
x:把模式空间中的内容和保持空间中的内容进行交换
d:删除模式空间中的内容
D:如果模式空间中的内容为多行时,删除模式空间中的第一行
n:读取匹配到的行的下一行到模式空间中(覆盖原内容)
N:读取匹配到的行的下一行到模式空间中(追加在原内容之后)
例如:显示偶数行的时候就可以这样实现:sed -n 'n;p' FILE
[root@server161 myfile]# nl /etc/passwd | head -n 10
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@server161 myfile]# nl /etc/passwd | head -n 10 | sed 'N;s/\n//g'
1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@server161 myfile]# nl /etc/passwd | head -n 10 | sed N
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@server161 myfile]# nl /etc/passwd | head -n 10 | sed 'N;s/\n//g'
1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin