18文本处理工具sed
sed,全称Stream EDitor,是一种流编辑器,它一次处理一行内容,但是它构思巧妙,功能强大,是运维工作中必不可少的文本处理工具,也是因为这样,被称作文本处理三剑客之一。
sed在处理时,把当前处理的行李存储在临时缓冲区中,这个区域被称作“模式空间pattern space”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾,文件内容并没有改变,除非你使用重定向存储输出或用选项直接修改源文件。sed主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等。除了pattern space,sed还有一个保持空间,叫做hold space,这个空间默认是空的,既不会自动清空也不会自动输出,其功能是当我们处理一行内容的时候,可以将模式空间内的文本转存至保持空间,通过两个空间的转换来实现更加强大的文本处理。
一、杂项知识整理
1、sed在使用的时候-i选项是非常危险的操作,但有些时候又必须修改原文件。这时为了避免错误修改了原文件,可以使用sed -i.bak(自定义后缀)‘’ file1此命令进行修改,.bak为自定义后缀名,命令会将原文件备份为file1.bak,然后再修改原文件。例如:
[root@localhost testdir]# sed -ri.bak '/\/bin\/bash/d' passwd [root@localhost testdir]# ls a aa b data passwd q qqq string.txt user userinfo a~ abc copytest lost+found passwd.bak qq shelltest test user.dir
2、nl命令:计算文件中的行号,将输出的文件内容自动加上行号。
-b 指定行号的方式:
a 表示不论是否为空行,也同样列出行号(类似cat -n)
t 如果有空行,空的哪一行不列出行号
二、命令详解及事例
1、用法:sed [option]… 'script' inputfile
script:地址定界编辑密令(两者没有分隔,是连续的)
常用选项:
-n 不输出模式空间中的内容至屏幕(静默模式)
-e 多点编辑,在每个命令之前加-e,便可以结合多个sed命令一起处理文本,不需要管道
-f 从指定文件中读取编辑脚本,每行一个编辑命令
[root@localhost testdir]# sed -f aaa /etc/issue CentOS 7.2 Kernel \r on AAAAAAAAAn \m [root@localhost testdir]# cat aaa s/a/AAAAAAAAA/
-r 支持使用扩展正则表达式
-i 直接编辑原文件
地址定界:
空地址:不给任何地址,对全文进行处理
单地址:
# 指定第#行
/PATTERN/ 被此模式匹配到的每一行
[root@localhost testdir]# cat /etc/issue CentOS 7.2 Kernel \r on an \m \d \l \n \r [root@localhost testdir]# sed -r '/\\/d' /etc/issue CentOS 7.2
地址范围:
#,# 从多少行到多少行
#,+# 从多少行到#+#行
#,// 从第#行到被模式匹配到的第一行
//,// 从被第一个模式匹配到的行到被第二个模式匹配到的行
[root@localhost testdir]# cat /etc/issue CentOS 7.2 Kernel \r on an \m \d \l \n \r \s \v \t \o [root@localhost testdir]# sed -r '/\\d/,/\\n/d' /etc/issue CentOS 7.2 Kernel \r on an \m \r \s \v \t \o
$ 最后一行
步进:
1~2 所有奇数行
[root@localhost testdir]# sed '1~2d' /etc/issue Kernel \r on an \m \l \r \v \o
2~2 所有偶数行
编辑命令:
d 删除pattern space中的内容
p 显示pattern space中的内容
a\text 在行后面追加文本text,支持使用\n实现追加多行
[root@localhost testdir]# sed 'a\newline\nnewline' /etc/issue CentOS 7.2 newline newline Kernel \r on an \m newline newline
i\text 在行前面追加文本,支持使用\n实现多行插入
c\text 把匹配到的行替换为此处指定的文本text
w/PATH/TO/SOMEFILE 保存模式空间中的内容至指定文件中
[root@localhost testdir]# sed -r '/\\/w/testdir/functions' /etc/issue CentOS 7.2 Kernel \r on an \m \d \l [root@localhost testdir]# ls aaa data lost+found passwd.bak string.txt user userinfo copytest functions passwd shelltest test user.dir userpasswd [root@localhost testdir]# cat functions Kernel \r on an \m \d \l
r/PATH/TO/SOMEFILE 读取指定文件中的内容至当前文件被模式匹配到的行后面,实现文件合并
= 每个被模式匹配到的行在其上一行添加一新行,内容是行号(是匹配到的行在原文中的第几行的行号)
[root@localhost testdir]# sed -r '/\\/=' /etc/issue CentOS 7.2 2 Kernel \r on an \m 3 \d 4 \l
!条件取反,写在模式后面,命令之前;地址定界!编辑命令
[root@localhost testdir]# sed -r '/\\/!=' /etc/issue 1 CentOS 7.2 Kernel \r on an \m \d \l
s///或者@@@或者### 查找替换
g 全局替换
w /PATH/TO/SOMEFILE 将替换成功的结果保存至指定文件中
p 显示替换成功的行
2、高级编辑命令
h 把模式空间中的内容覆盖至保持空间中
H 把模式空间中的内容追加至保持空间中
g 把保持空间中的内容覆盖至模式空间中
G 把保持空间中的内容追加至模式空间中
x 把模式空间中的内容与保持空间中的内容互换
n 覆盖读取匹配到的行的下一行到模式空间中
N 追加读取匹配到的行的下一行至模式空间中
d 删除模式空间中的行
D 删除多行模式空间中的所有行,追加之后的也会删除
3、高级编辑命令典例:
sed -n 'n:p' /FILE 显示偶数行
sed '1!G;h;$!d' FILE 逆序显示文件内容
sed '$!d' FILE 显示最后一行
sed '$!N;$!D' FILE 显示最后两行
sed '/^$/d;G' FILE 删除原有所有空白行,而后在所有非空白行后面添加一个空白行
sed 'n;d' FILE 显示奇数行
sed 'G' FILE 在原有的每行后面添加一个空白行
三、练习及作业
1、删除/etc/grub2.cfg文件中所有以空白开头的行行首的空白字符:
[root@localhost ~]# sed -r 's@^[[:space:]]+@@' /etc/grub2.cfg
2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符:
[root@localhost ~]# sed -r 's@^#[[:space:]]+@@g' /etc/fstab sed -n 's@^#[[:space:]]+@@p' /etc/fstab
3、在/etc/fstab每一行行首增加#号
[root@localhost ~]# sed 's@^@#@' /etc/fstab # ## ## /etc/fstab ## Created by anaconda on Tue Jul 19 04:56:39 2016 ## ## Accessible filesystems, by reference, are maintained under '/dev/disk' ## See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info ## #/dev/mapper/centos-root / xfs defaults 0 0 #UUID=595c35b0-15d0-46bb-a63a-b1b50f9202fd /boot xfs defaults 0 0 #/dev/mapper/centos-var /var xfs defaults 0 0 #/dev/mapper/centos-swap swap swap defaults 0 0 #/dev/sda5 swap swap defaults 0 0 #/dev/sda3 /testdir ext3defaults0 0 #/dev/cdrom /media/cdromiso9660defaults0 0
4、在/etc/fstab文件中不以#开头的行的行首增加#号。此处的&代表前面匹配到的内容,意思是在行首之前增加#号,若不使用&则会替换掉一个字符。例如
[root@localhost ~]# sed -r 's@root@&superman@g' /etc/passwd rootsuperman:x:0:0:rootsuperman:/rootsuperman:/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
[root@localhost ~]# sed -r 's@^[^#]@#&@' /etc/fstab
5、处理/etc/fstab路径,使用sed命令取出其目录名和基名:
目录名:锚定行尾,从后往前至第一个/为止替换为空
[root@localhost ~]# echo /etc/init.d/functions | sed -r 's@[^/]+/?$@@' /etc/init.d/
基名:分组,.*贪婪模式匹配。 锚定行尾。
[root@localhost ~]# echo /etc/init.d/functions/ | sed -r 's@(.*/)([^/])@\2@' functions/ [root@localhost ~]# echo /etc/init.d/functions | sed -r 's@(.*/)([^/])@\2@' functions [root@localhost ~]# echo /etc/init.d/aasdfasdg/functions/ | sed -r 's@(.*/)([^/]+/?$)@\2@' functions/ [root@localhost ~]# echo /etc/init.d/aasdfasdg/functions | sed -r 's@(.*/)([^/]+/?$)@\2@' functions
6、利用sed取出ifconfig命令中本机的IPv4地址
[root@localhost Packages]# ifconfig | sed -n -r '/(\b([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]\b)\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/p' inet 172.18.16.49 netmask 255.255.255.0 broadcast 172.18.16.255 inet 127.0.0.1 netmask 255.0.0.0
7、统计光盘Package目录下的所有rpm文件的以.分隔的倒数第二个字段的重复次数。
[root@localhost Packages]# ls | rev | cut -d. -f2 | rev | sort | uniq -c 2000 i686 2938 noarch 1 TRANS 4069 x86_6 [root@localhost Packages]# ls *.rpm | sed 's@.rpm$@@' | sed -r 's@(.*)(\..*$)@\2@' | sort | uniq -c 2000 .i686 2938 .noarch 4069 .x86_64
8、用正则表达式表示如下内容:
IPv4地址:
ifconfig | sed -n -r '/(\b([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]\b)\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/p'
身份证号:
egrep "\<((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|(71|81|82))([0-9]){4}(19|20)([0-9]){2}((0[1-9])|(1[0-2]))(0[1-9]|([0-9])|(2[0-9])|(3[0-1]))([0-9]){3}([0-9]|X)\>" filename
手机号:
grep -E -o "^\b1[3578][0-9]{9}\b"
邮箱:
egrep "\<([[:alnum:]]+(-|_)*[[:alnum:]]*)\>@([[:alnum:]]+\.)+[[:alnum:]]+" mail
原创文章,作者:SilencePavilion,如若转载,请注明出处:http://www.178linux.com/31526