十六、流编辑器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]'
相关推荐
AlfredZhao1 天前
生产环境里,为什么不建议把普通端口直接暴露到公网?
linux·https·443·80
戴为沐2 天前
Linux内存扩容指南
linux
zylyehuo3 天前
Linux 彻底且安全地删除文件
linux
用户805533698033 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297913 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
乘云数字DATABUFF3 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
Web3探索者5 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo5 天前
Linux系统中网线与USB网络共享冲突
linux
荣--5 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森5 天前
动手实战学 Docker — 从零到集群编排完全指南
运维