十六、流编辑器sed(stream editor)

一、sed简介

sed是一种流编辑器,处理时,把当前处理的行存储在临时缓冲区中,称为模式空间,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。

二、sed的语法

1.基本语法

cpp 复制代码
sed OPTIONS... [SCRIPT] [INPUTFILE...]

2.常用参数详解

-n,--quiet,--silent:不输出模式空间中的内容,使用安静模式,在一般sed的用法中,所有来自STDIN的数据一般都会被列出到屏幕上,但如果加上-n参数后,则只有经过sed特殊处理的那一行才会被列出 来;

-i:直接编辑原文件,而不是由屏幕输出,默认不对原文件进行操作;

-e:直接在命令行模式上进行sed的动作编辑,多个子命令之间也可以用分号隔开; sed -e 'command1;command2... filename 或者 sed -e 'command1' -e 'command2' ......filename

-r:使用扩展正则表达式;

-f:直接将sed的动作写在一个文件内,-f filename则可以执行filename内的sed动作。

三.模式空间中的编辑操作

1.地址的定界

|----------------------------|------------------|----------------------------------------|
| 地址定界 | 示例 | 说明 |
| 不写地址定界 | | 表示对文件所有行进行处理 |
| num1,num2 | 1,3或者1,$ | 对文件的1-3行内容进行处理;如果是$表示文件 的最后一行 |
| num1,+N | 1,+3 | 对文件的num1行以及以后的N行内容进行处理 |
| first~step | 1~2 | 对文件的1,3,5,7,......的行内容进行处理 |
| /pattern/ | /^root/,/r/I | 对任何能够被正则表达式匹配到的行进行处理 |
| \%pattern% | \%/r% | 可以使用其他的边界符号(例如#),对任何能 够被正则表达式匹配到的行进行处理 |
| /pattern1/,/pattern2/ | /^root/,/^adm/ | 表示正则表达式1和正则表达式2匹配到的行和两 个正则表达式之间的所有行 |
| 0,/pattern1/或者1,/pattern1/ | 0,/^adm/ | 从第一行开始到能够被正则表达式匹配到的行之 间的所有内容 |

示例:

生成测试文件

cpp 复制代码
[root@sen shell]# head -n 5 /etc/passwd > testfile

a.替换文件中所有:为@@@

cpp 复制代码
[root@sen shell]# sed 's/:/@@@/g' testfile
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

b.替换1-3行的:

cpp 复制代码
[root@sen shell]# sed '1,3s/:/@@@/g' testfile
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

c.替换1行和3行的:

cpp 复制代码
[root@sen shell]# sed -e '1s/:/@@@/g' -e '3s/:/@/g' testfile
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

d.替换2行及其后2行:

cpp 复制代码
[root@sen shell]# sed -e '2,+2s/:/@@@/g' -e '3s/:/@/g' testfile
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

e.每隔1行替换:

cpp 复制代码
[root@sen shell]# sed -e '2~2s/:/@@@/g' testfile
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

f.带sbin字符忽略大小写的行替换:

cpp 复制代码
[root@sen shell]# sed -e '/SBIN/Is/:/@@@/g' testfile
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

g.daemon和lp字符之间的行替换:

cpp 复制代码
[root@sen shell]# sed -e '/daemon/,/lp/s/:/@@@/g' testfile
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

h.第1行到adm之间的

cpp 复制代码
[root@sen shell]# sed -e '1,/adm/s/:/@@@/g' testfile
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

i.adm到最后一行的

cpp 复制代码
[root@sen shell]# sed -e '/adm/,$s/:/@@@/g' testfile
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

j.其他sed分隔符的指定

cpp 复制代码
[root@sen shell]# sed -e '\%adm%,$s%:%@@@%g' testfile
[root@sen shell]# sed -e '\#adm#,$s#:#@@@#g' testfile

2.常用编辑命令

|----------------------------|----------------------------------------------------------------------------------------------------------------|
| 对文件行内容的编辑 | 说明 |
| d | 删除匹配到的行 |
| p | 打印匹配到的行 |
| a 文本内容 | 将文本内容添加到匹配到的行的下一行 |
| i 文本内容 | 将文本内容添加到匹配到的行上一行 |
| c 文本内容 | 用文本内容替换匹配到的所有行 |
| r | 读入文件内容追加到匹配行后面 |
| R | 读入文件一行内容追加到匹配行后面 |
| w /dir/filename | 将匹配到的内容另存到/dir/filename中 |
| s/pattern/replacement/flag | 根据正则表达式进行匹配,将匹配到的内容替换为replacement, flag可以指定g(表示全局替换,默认只替换每行第一个)num1(表 示对匹配到的第几个内容进行替换),i(不区分大小写),p(如 果成功替换则打印) |

示例:

生成测试文件
cpp 复制代码
[root@sen shell]# sed -e '\#adm#,$s#:#@@@#g' testfile
a.删除行
cpp 复制代码
[root@sen shell]# sed '1d' testfile
[root@sen shell]# sed '$d' testfile
[root@sen shell]# sed '/root/d' testfile
[root@sen shell]# sed '/root/!d' testfile
b.显示行
cpp 复制代码
[root@sen shell]# sed -n '1p' testfile
[root@sen shell]# sed -n '$p' testfile
[root@sen shell]# sed -n '/root/p' testfile
[root@sen shell]# sed -n '/root/!p' testfile
c.添加行
cpp 复制代码
[root@sen shell]# sed '1ahello world' testfile
[root@sen shell]# sed '$ahello world' testfile
[root@sen shell]# sed '/adm/ahello world' testfile
[root@sen shell]# sed '/adm/ahello world' testfile
[root@sen shell]# sed '/adm/!ahello\nworld' testfile
d.插入行
cpp 复制代码
[root@sen shell]# sed '1ihello world' testfile
[root@sen shell]# sed '$ihello world' testfile
[root@sen shell]# sed '/adm/ihello world' testfile
[root@sen shell]# sed '/adm/ihello world' testfile
[root@sen shell]# sed '/adm/!ihello\nworld' testfile
e.替换行
cpp 复制代码
[root@sen shell]# sed '1chello world' testfile
[root@sen shell]# sed '$chello world' testfile
[root@sen shell]# sed '/adm/chello world' testfile
[root@sen shell]# sed '/adm/chello world' testfile
[root@sen shell]# sed '/adm/!chello\nworld' testfile
f.整合文件
cpp 复制代码
[root@sen shell]# vim numfile1
1
5
6
[root@sen shell]# vim numfile2
2
3
4
[root@sen shell]# sed '1rnumfile2' numfile1
[root@sen shell]# sed '1Rnumfile2' numfile1
g.保存处理结果
cpp 复制代码
[root@sen shell]# sed '/root/w file' testfile
[root@sen shell]# cat file
root:x:0:0:root:/root:/bin/bash
h.字符替换
cpp 复制代码
[root@sen shell]# sed 's/:/##/' testfile
[root@sen shell]# sed 's/:/##/2' testfile
[root@sen shell]# sed 's/:/##/g' testfile
[root@sen shell]# sed 's/^./##/g' testfile
[root@sen shell]# sed 's/^\<[a-Z]*[a-Z]\>//' testfile
元素向后引用
[root@sen shell]# sed 's/^\(...\)\(t\)/\2/g' testfile
t:x:0:0:root:/root:/bin/bash

3.特殊符号的使用

|------|------------------------------------|
| 特殊符号 | 说明 |
| ! | 对指定行以外的所有行应用命令 |
| = | 打印当前行行号 |
| ~ | "first~step"表示从first行开始,以步长step递增 |
| & | 代表匹配到的内容 |
| ; | 实现一行命令语句可以执行多条sed命令 |
| {} | 对单个地址或地址范围执行批量操作 |
| + | 地址范围中用到的符号,做加法运算 |

示例:

!示例
cpp 复制代码
[root@sen shell]# sed -n '/root/!p' testfile
=示例
cpp 复制代码
[root@sen shell]# sed   '=' testfile
~示例
cpp 复制代码
[root@sen shell]# sed '1~2s/:/##/g' testfile
&示例
cpp 复制代码
[root@sen shell]# sed 's/:/^&^/g' testfile
; 示例
cpp 复制代码
[root@sen shell]# sed -n '1p;3p' testfile
{}示例
cpp 复制代码
[root@sen shell]# sed -n '1,3p;1,3=' testfile
[root@sen shell]# sed -n '1,3{p;=}' testfile
+示例
cpp 复制代码
[root@sen shell]# sed -n '1,+1p' testfile

四、模拟面试训练

1.给定一个文件,要求在文件每一行前加入行号并用空格隔开内容

cpp 复制代码
[root@sen shell]# sed '=' testfile | sed 'N;s/\n/ /g'

2.给定文件按要求完成文件内容

cpp 复制代码
文件内容如下:
 123abc456
 456def123
 567abc789
 789def567
 
要求输出:
 456ABC123
 123DEF456
 789ABC567
 567DEF789
cpp 复制代码
[root@sen shell]# sed -r 's/([0-9]{3})(.*)([0-9]{3})/\3\2\1/' b.txt | tr -s 
'[a-z]' '[A-Z]'
相关推荐
测试者家园5 分钟前
SkyWalking环境搭建
运维·软件测试·微服务·jenkins·skywalking·性能监控·质量效能
码农不屈的一生1 小时前
ARM架构服务器安装部署KVM虚拟化环境
运维·服务器·arm开发·架构
vvw&1 小时前
如何在 Ubuntu 22.04 上部署 Nginx 并优化以应对高流量网站教程
linux·运维·服务器·后端·nginx·ubuntu·性能优化
速盾cdn1 小时前
速盾:服务器CDN加速解析的好处有哪些呢?
运维·服务器
maply1 小时前
常用的公共 NTP(网络时间协议)服务器
运维·服务器·网络
网硕互联的小客服1 小时前
如何排查香港服务器上的权限问题
linux·运维·服务器·网络·云计算
缘友一世1 小时前
1panel fail2ban助力服务器SSH以及删除SSH登陆日志
运维·服务器·ssh
果汁分你一半l1 小时前
shell脚本的使用
linux·vim
Days20501 小时前
慎用翼讯科技服务器以及不知名服务器的说明
运维·服务器·科技
西西偷西瓜2 小时前
云效流水线使用Node构建部署前端web项目
运维·前端·自动化