首页 > 代码库 > sed用法
sed用法
1. sed概述
sed是Stream EDitor的缩写,意为流式文本编辑器。sed名字来源于其功能,可以想象污水流经污水处理点后流出更为干净的水,sed也一样,文本中的数据流可以使用sed这个文本处理工具中各种编辑命令进行处理,最终以另一种格式输出。
sed是一种‘非交互式‘的编辑器,一次只处理一行内容。在处理时,会先将待处理的一行暂存至内存中的某一段缓存空间,这段缓存空间称为“模式空间(Pattern Space)”。接着使用sed命令处理模式空间中的内容,而处理后的内容默认输出至标准输出,默认不修改原文件。然后接着处理下一行,直至最后一行。sed常用来重复编辑一个或多个文件,简化对文件的操作。
此外,除了"模式空间(Pattern Space)",sed在使用一些高级命令(例如:g/G, h/H, x)时还会使用到保持空间(Hold Space),保持空间用于保存模式空间的内容,但不管模式空间和保持空间如何工作,最终只能由模式空间输出至标准输出。
2. sed处理流程
当我们指定用sed命令去处理某个文件时,其处理流程如下:
① 读入新的一行进入模式空间(pattern space); ② 从指定的操作指令中取出第一条指令,判断该行是否被pattern匹配; ③ 如果不匹配,则忽略后续的编辑指令,在静默模式下不会输出,否则默认输出; ④ 如果匹配,并针对缓存的行执行后续的编辑命令。执行后,返回第2步继续取出下一条指令。 ⑤ 当应用所有指令后,将模式空间中缓存的处理结果输出;返回第1步读取文本的下一行; ⑥ 当所有行都处理之后,结束。
总结一下,sed的处理是这样的:把要处理的一行放进模式空间中,先看看是否要默认输出这一行至标准输出;接着对模式空间匹配到的行进行处理(执行一个或一个以上的编辑命令);最后再把模式空间中匹配到的行的处理结果输出至标准输出。
3. sed命令使用
命令格式:
sed [option]... ‘script‘ [FILE]... sed 选项 ‘地址定界编辑命令‘ 文件
常用选项:
-n:静默模式,抑制默认输出;
-r:支持使用扩展正则表达式元字符;、
-i:直接修改原文件;
-i.bak:直接修改原文件,但会生成一个原文件的备份文件(后缀名为.bak)
-e:用于实现多个‘script‘一次执行;
-f /PATH/TO/SED_SCRIPT_FILE:可使用sed脚本文件来执行对文本的处理操作。
地址定界:
(1)不接地址:全局应用于每一行,即匹配所有行;
(2)单地址:
N:第N行;
/pattern/:由pattern匹配到的行;
$:最后一行;
(3)地址范围:
M,N:从第M行到第N行之间的所有行;
M,+N:从第M行开始到M+N之间的所有行;
N,$:从第N行到最后一行之间的所有行;
M,/pattern/:从第M行到由pattern第一次匹配到的行之间的所有行;
/pattern1/,/pattern2/:从由pattern1第一次匹配到的行到由pattern2第一次匹配到的行之间的所有行;
(4)步进表示法:
1~2:所有奇数行;例如: sed ‘1~2p‘ test
2~2:所有偶数行;例如: sed ‘2~2p‘ test
编辑命令:
编辑命令是对模式空间中匹配到的行进行编辑处理操作。编辑命令有基本命令和高级命令,基本命令一次只能处理一行,而高级命令可实现一次处理多行(或理解为将多行视为一行来处理)。
(a)基本命令: d:delete, 删除模式空间中匹配到的行; p:print, 显示模式空间中被匹配到的行; a \TEXT:append, 在指定行后追加文本TEXT,支持使用\n实现多行追加; i \TEXT:insert, 在指定行前插入文本TEXT,支持使用\n实现多行插入; c \TEXT:将指定行的内容替换为文本TEXT; w /PATH/TO/SOMEFILE:write, 保存模式空间中匹配到的行至指定的文件中; r /PATH/FROM/SOMEFILE:read, 将指定文件的内容读取至当前模式空间中被匹配到的行后面, 常用于实现文件合并; s/pattern/replaces/:查找替换;分隔符可自行指定,常用的分隔符有/, #, @等; 替换标记: g:全局替换; w /PATH/TO/SOMEFILE:将替换的结果保存至指定文件中; p:显示替换成功的行; y:用于(对应)转换字符; =:打印行号; !:条件取反;即对不被模式匹配到的行执行编辑命令;格式为:地址定界!编辑命令 l:打印行号,并显示控制字符; q:读取匹配到的行后退出; (b)高级命令: n:覆盖读取匹配到的行的下一行至模式空间中; N:追加读取匹配到的行的下一行至模式空间中,并用\n连接两行; D:删除模式空间的第一行的内容,并在模式空间中继续执行编辑命令; P:打印模式空间的第一行的内容; h:hold, 将模式空间中的内容覆盖至保持空间中; H:Hold, 将模式空间中的内容追加至保持空间中; g:get, 将保持空间中的内容覆盖至模式空间中; G:Get, 将保持空间中的内容追加至模式空间中; x:exchange, 将模式空间中的内容与保持空间中的内容互换; 注意: (1) sed保持空间(Hold Space):用于保存模式空间的内容; (2) h, H, g, G, x这5个高级命令会使用到sed的保持空间;
4. sed使用示例
4.1. 以行为单位新增/删除
将/etc/passwd的内容输出并且打印行号,同时在第1行之前插入两行文本,第一行内容为"How are you?",第二行内容为"How old are you?":
[root@localhost ~]# nl /etc/passwd | sed ‘1i \How are you?\nHow old are you?‘ How are you? How old are you? 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 .....(后面省略)..... 命令解释: 可使用\n以实现多行插入文本。
在/etc/passwd第2行之后追加文本"Drink tea?":
[root@localhost ~]# nl /etc/passwd | sed ‘2a \Drink tea?‘ 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin Drink tea? 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 .....(后面省略).....
删除/etc/passwd第2行至第5行内容:
[root@localhost ~]# nl /etc/passwd | sed ‘2,5d‘ 1 root:x:0:0:root:/root:/bin/bash 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 1 0operator:x:11:0:operator:/root:/sbin/nologin .....(后面省略)..... 命令解释: 因为在模式空间中,第2行~第5行中每一行会被匹配到,而d命令会删除在模式空间中匹配到的行, 因此这几行不输出。
删除/etc/passwd中除了第一行之外的所有行:
[root@localhost ~]# nl /etc/passwd | sed ‘1!d‘ 1 root:x:0:0:root:/root:/bin/bash
把文本第一行之后的空白行删除:
待处理的test文本内容如下: [root@localhost ~]# cat test aaaaaa bbb cc d e [root@localhost ~]# [root@localhost ~]# sed ‘1{n;d}‘ test aaaaaa bbb cc d e [root@localhost ~]# 命令解释: 因为地址匹配的是第一行,所以两个指令是针对第一行来进行处理的;当第一行读进来后,因为第 一行符合匹配条件,所以会对第一行执行处理命令,首先执行的是n命令,即覆盖追加第二行至第一 行中,在此之前第一行会默认输出至屏幕,而后在模式空间中的第一行被文本中的第二行覆盖,接 着再执行d命令,即把模式空间中的第一行(即文本的第二行删除)。接着再读取文本的第三行,不满 足匹配条件,因此不执行命令并默认输出,接着读取文本的第四行...... 注意:对某一行执行多次处理可用{}将处理命令command括起来,花括号内的每个命令之间用分号分 隔。
4.2. 以行为单位的替换与打印
将/etc/passwd第三行替换为文本"This is the third line.":
[root@localhost ~]# nl /etc/passwd | sed ‘3c \This is the third line.‘ 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin This is the third line. 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 .....(后面省略).....
使用编辑命令y实现对应转换字符:
待处理的test文本内容如下: [root@localhost ~]# cat test a b c d aa abc [root@localhost ~]# 将字符a、b、c分别替换为x、y、z: [root@localhost ~]# sed ‘y/abc/xyz/‘ test x y z d xx xyz [root@localhost ~]# 命令解释: 因为没有接地址,因此是匹配全局;
用sed显示/etc/passwd的行号:
[root@localhost ~]# sed ‘=‘ /etc/passwd 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 .....(后面省略)..... 命令解释: 每个行号占用一行,显示行号,再显示行的内容。
只读/etc/passwd的前10行:
[root@localhost ~]# sed ‘10q‘ /etc/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 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin 命令解释: 如果使用sed -n ‘1,10p‘ /etc/passwd,那么当文本文件非常大甚至有几百万行时,根据sed工作流 程,它会处理每一行,即便我们需要的仅是显示前10行,这是非常浪费CPU资源的,因此可使用q命 令,指定sed处理完前10行即退出。
4.3. 数据的查找替换
搜索/etc/passwd中root用户对应的一行,将‘bash‘改为‘blueshell‘,再输出该行:
[root@localhost ~]# sed -n ‘/^root/{s/bash/blueshell/;p}‘ /etc/passwd root:x:0:0:root:/root:/bin/blueshell
如果替换好该行的bash为blueshell后就退出,则:
[root@localhost ~]# sed ‘/^root/{s/bash/blueshell/;q}‘ /etc/passwd root:x:0:0:root:/root:/bin/blueshell
在两个数字之间添加‘:‘:
待处理的test文本内容如下: [root@localhost ~]# cat test 123 321 添加‘:‘: [root@localhost ~]# sed -r ‘s/([0-9])([0-9])([0-9])/\1:\2:\3/‘ test 1:2:3 3:2:1
只用sed命令完成对"ifconfig ens33"命令执行结果的处理,要求输出为网卡ens33的IP地址:
先尝试匹配‘inet‘: [root@localhost ~]# ifconfig ens33 | sed -n ‘/inet/p‘ inet 10.10.10.140 netmask 255.255.255.0 broadcast 10.10.10.255 inet6 fe80::20c:29ff:fec8:ff4e prefixlen 64 scopeid 0x20<link> 再过滤掉inet6这一行: [root@localhost ~]# ifconfig ens33 | sed -n ‘/inet\>/p‘ inet 10.10.10.140 netmask 255.255.255.0 broadcast 10.10.10.255 或者: [root@localhost ~]# ifconfig ens33 | sed -n ‘/inet\b/p‘ inet 10.10.10.140 netmask 255.255.255.0 broadcast 10.10.10.255 接着删除IP前面的部分: [root@localhost ~]# ifconfig ens33 | sed -n ‘/inet\>/p‘ | sed ‘s/^.*inet //‘ 10.10.10.140 netmask 255.255.255.0 broadcast 10.10.10.255 再删除IP后面的部分,得到最终结果: [root@localhost ~]# ifconfig ens33 | sed -n ‘/inet\>/p‘ | sed ‘s/^.*inet //‘ | sed ‘s/ netmask.*$//‘ 10.10.10.140 命令解释: 使用sed对列进行处理时,通常使用搜索替换s/pattern/replaces/,常使用的替换标记是g;不过 sed在对列的处理上不如awk。
将/etc/passwd第1到第5行中shell为/bin/bash的用户的shell改为‘/bin/greenshell‘,再输出:
[root@localhost ~]# sed -n ‘1,5{s@/bin/bash@/bin/greenshell@;p}‘ /etc/passwd root:x:0:0:root:/root:/bin/greenshell 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 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 或者: [root@localhost ~]# sed -n ‘1,5{s/\/bin\/bash/\/bin\/greenshell/;p}‘ /etc/passwd root:x:0:0:root:/root:/bin/greenshell 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 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 命令解释: 当分隔符出现在模式或替换文本中时,需要进行转义;或者使用其他的分隔符,例如:s@@@, s###, s%%%, ...
4.4. 高级命令的使用
把文本的前两行拼接成一行,中间用空格隔开:
待处理的test文本内容如下: [root@localhost ~]# cat test this is a boy c d e 拼接前两行,中间用空格隔开: [root@localhost ~]# sed ‘1{N;s/\n/ /}‘ test this is a boy c d e 命令解释: 处理时,把第一行读取进模式空间中,而第一行能够被匹配,因此针对第一行执行花括号内的操作 :先追加读取第二行至模式空间中,第一行与第二行用\n连接;接着执行搜索替换,将‘\n‘替换为 空格,这样就实现拼接了。接着读取文本的第三行至模式空间中,因为不被匹配,因此不执行编辑 命令,在非静默模式下会直接输出模式空间的内容,因此直接输出‘c‘;接着读取第四行......
如果出现空白行只保留一个空白行,即删除多余的空白行,行与行之间最多只能有一个空白行:
待处理的test文本内容如下: [root@localhost ~]# cat test a b c d [root@localhost ~]# 删除多余的空白行: [root@localhost ~]# sed ‘/^$/{N;/\n$/D}‘ test a b c d 解决思路: 首先用/^$/去匹配空白行,针对被匹配到的空白行执行编辑命令;接着可用命令N追加下一行至匹配 到的空白行之后,且用\n连接,这时可根据模式空间中的第二行(在这里是\n之后的内容)是否为空 ,去判断空白行是否只有一行;如果\n后为非空字符串(例如b),则说明模式空间中只有一个空白行 ;如果\n为空,则不止一个空白行,此时模式空间为:[]\n[],[]代表空白行;这时可使用命令D删 除模式空间中的第一行的内容(在这里第一行的内容为[])。 用同样的思路解释如下命令的执行结果: [root@localhost ~]# sed ‘/^$/{N;/\n$/d}‘ test a b c d
显示以下文本中‘a‘的上一行的内容:
待处理的test文本内容如下: [root@localhost ~]# cat test 1 a 2 b 3 c 4 a c 要求只显示a上一行的内容: [root@localhost ~]# sed -n ‘N;/a$/P‘ test 1 4 解决思路: 读取一行进模式空间后,先追加下一行进来,判断是否是以‘\na‘结束,因此可用‘a$‘来作为追加下 一行后的匹配条件;如果是以‘\na‘结束,则打印上一行;如果不是以‘\na‘结束,则使用静默模式 不输出。 命令解释: 第一行读取进模式空间时,先追加文本第二行进来,两者在模式空间中以\n连接,接着看看模式空 间中的内容是否满足模式/a$/的匹配条件;因为匹配,所以输出上一行,而加上-n选项抑制默认输 出,因此只输出一个‘1‘;接着开始读取下一行‘2‘进入模式空间中,接着追加下一行‘b‘进来,模式 空间中的内容为:2\nb;因为不匹配,所以在静默模式下不输出模式空间中的内容;接着读取下一 行进模式空间中,再追加一行,此时模式空间的内容为:3\nc;......再读取、追加,模式空间的 内容为:4\na;符合匹配,输出‘4‘;读取下一行,不再追加,且不符合匹配,在静默模式下不输出 。 尝试其他方法: [root@localhost ~]# sed ‘N;/a$/P;D‘ test 1 4 c 分析: 处理时,先把第一行放进模式空间中,追加下一行,模式空间内容为:1\na,因此符合条件,打印 模式空间中的第一行1;接着删除模式空间中的第一行1;然后追加读取下一行2,此时模式空间内容 为a\n2,不符合匹配条件,因此不打印模式空间第一行,而删除模式空间中的第一行内容;再追加 ,模式空间内容为:2\nb;......当模式空间内容剩下:a\nc时,因为不符合匹配条件,不打印模 式空间中的第一行,而删除模式空间中的第一行,最后模式空间只剩下c,因为不是静默模式,所以 默认输出c,故有此结果。 尝试: [root@localhost ~]# sed ‘N;/a$/P;d‘ test 1 4 c 分析: 处理时,先把第一行放进模式空间中,追加下一行,模式空间内容为:1\na,因此符合条件,打印 模式空间中的第一行1;接着删除模式空间中的行;然后读取文本的下一行‘2‘进入模式空间,追加 一行‘b‘,此时模式空间中的内容为:2\nb,不符合匹配条件/a$/,直接执行d命令删除模式空间中 匹配到的行(此时匹配条件为全局);......最后模式空间中只剩下‘c‘,在不是静默模式的情况下默 认输出。 要想把刚才的结果的最后一行‘c‘删除掉,可尝试: [root@localhost ~]# sed ‘$!N;/a$/P;D‘ test 1 4 符合要求; [root@localhost ~]# sed ‘$!N;/a$/P;d‘ test 1 4 同样符合要求; 但若将test文本改为这样: [root@localhost ~]# cat test 1 a 2 b 3 c 4 a a 即把最后一行改为‘a‘。 这时再次执行上述命令: [root@localhost ~]# sed ‘$!N;/a$/P;d‘ test 1 4 a 符合要求; [root@localhost ~]# sed ‘$!N;/a$/P;D‘ test 1 4 a a 不符合要求; 分析: 当输出4时,模式空间内容为:a,因为此时本行‘a‘不是文本的最后一行,所以会追加文本的下一行 (文本最后一行)至模式空间中,此时模式空间内容变为:a\na,符合匹配条件,打印模式空间的上 一行,而后删除模式空间的第一行‘a‘,此时模式空间只剩下‘a‘,因为没有加-n选项所以默认输出 此时模式空间中剩下的内容‘a‘。 命令解释: 很多情况下,N、P、D这三个命令都是可以结合使用的,P命令都是用在N命令之后、D命令之前的。 这三个命令结合起来可形成一个输入输出的循环,并且每次只打印一行:读入一行后,N命令继续读 下一行,P命令打印第一行,D命令删除第一行,执行完成后回到最开始重复该过程。
在文本的每一行之后都添加一行空白行:
待处理的test文本内容如下: [root@localhost ~]# cat test a b c d e [root@localhost ~]# 使用命令G添加空白行: [root@localhost ~]# sed ‘G‘ test a b c d e [root@localhost ~]# 命令解释: 命令G是将保持空间中的内容追加至模式空间中,而保持空间中的内容为空白,在追加后原有模式空 间中的内容多了:\n [];其中[]表示空白行。
将文本全部换为空白行:
待处理的test文本内容如下: [root@localhost ~]# cat test a b c d e [root@localhost ~]# 使用命令G: [root@localhost ~]# sed ‘g‘ test [root@localhost ~]# 命令解释: 命令g是将保持空间中的内容覆盖至模式空间中,而保持空间默认为空。
命令H、x的使用:
待处理的test文本内容如下: [root@localhost ~]# cat test a b c d e [root@localhost ~]# 执行H命令: [root@localhost ~]# sed ‘H;$x‘ test a b c d a b c d e [root@localhost ~]# 命令解释: 命令H是将模式空间中的内容追加至保持空间中;在读取文本最后一行‘e‘进入模式空间后,先追加 至保持空间中,而后因为符合匹配条件(最后一行‘$‘),因此执行x命令,即将模式空间中的内容与 保持空间中的内容互换,而保持空间此时的内容为:[] \n a \n b \n c \n d \n e,因此得到以上 执行结果。
4.5. sed 保持空间-综合示例
使用逗号拼接行: [root@localhost ~]# sed ‘H;$!d;${x;s/^\n//;s/\n/,/g}‘ test 1,2,3,4
5. sed与vim,awk,grep的比较
总的来说,相对于vim这种强大的“交互式”文本编辑器而言,sed的优势在于可以重复对文本的行进行处理,通常在对很多匹配到的行执行多条编辑命令时,这种优势体现更为明显,而如果用vim进行“交互式”处理时,则相当耗费时间,并且操作简单重复且繁琐枯燥。
sed与awk,grep这三种工具作为Linux文本处理三剑客,各有各自的优势,谁也替代不了谁。只是相比较而言,sed与awk功能更加强大,已独立成一种语言。grep在实现过滤文本时效率要比其他工具高得多;sed作为流编辑器在对文本进行处理时功能非常强大,默认不会修改原文件;sed虽然有过滤功能,但实现起来效率低不如grep;而sed在对列的处理能力上相比awk要差得多,awk也是一种文本处理语言,在Linux上的实现为gawk(GNU awk),它把文本看成数据库,将文本分成许多段,然后分别对这些段进行处理或格式化后输出,且不修改原文件;awk是报告生成器,可格式化生成文本,因此非常适于生成具有一定格式的报告文本。
grep, sed, awk这几个工具在生产环境中经常搭配使用,结合文本查找工具find,可实现快速查找、过滤、处理文本的功能。
本文出自 “Tab” 博客,请务必保留此出处http://xuweitao.blog.51cto.com/11761672/1897752
sed用法