Shell脚本三剑客之sed


行编辑器sed介绍

sed是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(增加,删除,替换,添加,移动等)最后输出所以行或仅输出处理的某些行。
sed也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于shell脚本中,用以完成各种自动化处理任务

1、工作流程

读取:sed从输入流 (文件、管道、标准输入) 中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)

执行:默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行

显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完

注意:默认情况下,所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

2.基本用法


sed [选项] ‘操作’ 参数
其中,“参数”是指操作的目标文件,当存在多个操作对象时,文件之间用逗号分隔。


sed  [选项] -f scriptfile 参数
而scriptfile 表示脚本文件,需要用“-f”选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件

3.常用选项

**-n 不输出模式空间内容到屏幕,即不自动打印,仅显示处理后的结果**
-e 表示用指定命令或者脚本来处理输入的文本文件
-f FILE 从指定文件中读取编辑脚本
**-r, -E 使用扩展正则表达式
-i	直接编辑文本文件
-i.bak 备份文件并原处编辑**
-s     将多个文件视为独立文件,而不是单个连续的长文件流

4.常见的sed操作指令

**“操作”**用于指定对文件操作的动作行为,也就是 sed 的命令。通常情况下是采用的“[n1[,n2]]”操作参数的格式。n1、n2 是可选的,不一定会存在,代表选择进行操作的行数,如操作需要在 5~20 行之间进行,则表示为“5,20 动作行为”。常见的操作包括以下几种。

p  打印,如果同时指定行,表示打印指定行,如果不指定行,则表示打印所有内容,如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。
Ip 忽略大小写输出
d 删除模式空间匹配的行,并立即启用下一轮循环
a  增加,在当前行下面增加一行指定内容;[\]text 在指定行后面追加文本,支持使用\n实现多行追加
i  插入,在选定行上面插入一行指定内容;[\]text 在行前面插入文本
c  替换,将选定行替换为指定内容;[\]text 替换行为单行或多行文本
s  替换,替换指定字符;s 的动作可以搭配正规表示法!例如 1,20s/old/new/g
y  字符转换。
w file 保存模式匹配的行至指定文件
r file 读取指定文件的文本至模式空间中匹配到的行后
= 为模式空间中的行打印行号
! 模式空间中匹配行取反处理
q           结束或退出sed
     

Sed用法示例

直接输入sed会出现sed用法

[root@yzq mnt]#sed

sed ’ ’ 不加选项,不加操作,不加参数默认将输入内容打印出来

[root@yzq mnt]#sed ''
a
a
sd
sd
pp
pp

单独加上参数,查看文件内容

[root@yzq mnt]#sed '' txt 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

sed带有自动打印功能,p操作又再打印一遍

[root@yzq mnt]#sed 'p' txt 
1 www.kgc.com
1 www.kgc.com
2 mail.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
4 linux.kgc.com
5 blog.kgc.com
5 blog.kgc.com

-n:只显示处理后的结果,但是不修改文件原本的内容
只p打印

[root@yzq mnt]#sed -n 'p' txt 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

指定行数打印输出(可以指定单行或多行)

指定打印某行

[root@yzq mnt]#sed -n '2p' txt 
2 mail.kgc.com
[root@yzq mnt]#sed -n 3p txt 
3 ftp.kgc.com

打印3-5行

[root@yzq mnt]#sed -n '3,5p' txt 
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

打印某行和之后几行

[root@yzq mnt]#sed -n '2,+2p' txt 
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com

打印某些行
打印奇数行,1表示起始行,~2表示步长

[root@yzq mnt]#sed -n '1~2p' txt 
1 www.kgc.com
3 ftp.kgc.com
5 blog.kgc.com

输出所有奇数行,n 表示读入下一行资料,输出1-5行的奇数行可用‘1,5{p;n}’表示

[root@yzq mnt]#sed -n 'p;n' txt 
1 www.kgc.com
3 ftp.kgc.com
5 blog.kgc.com

输出所有偶数行,n 表示读入下一行资料

[root@yzq mnt]#sed -n 'n;p' txt 
2 mail.kgc.com
4 linux.kgc.com

输出第3行至行尾的偶数行

[root@yzq mnt]#sed -n '3,${n;p}' test 
antlr-runtime-3.4.jar
archaius-core-0.7.6.jar
aspectjweaver-1.9.5.jar
bcprov-jdk15-1.46.jar
checker-compat-qual-2.5.5.jar

打印第一行和第三行

[root@yzq mnt]#sed -n '1p;3p' txt 
1 www.kgc.com
3 ftp.kgc.com

匹配内容打印行
//中间输入需要匹配的内容,输出包含ftp的行

[root@yzq mnt]#sed -n '/ftp/p' txt 
3 ftp.kgc.com

输出从第三行开始,一直到第一个包含5的行

[root@yzq mnt]#sed -n '3,/5/p' 1.txt
3
4
5

输出一共3个1为止的行,即找到3个1为止

[root@yzq mnt]#sed -n '/1/,3p' 1.txt
1
2
3
10
11

还可以匹配正则表达式
输出以root开头的行到以b开头的行(不是只输出这两行)

[root@yzq mnt]#sed -n '/^root/,/^b/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

输出包含内容的行所在的行号,等号(=)用来输出行号

[root@yzq mnt]#sed -n '/run/=' test 
4
[root@yzq mnt]#sed -n '=' test 
1
2
3
4
5
6
7
8
9
10
11
12

输出包含单词linux 的行,<、>代表单词边界

[root@yzq mnt]#sed -n '/\<linux\>/p' txt 
4 linux.kgc.com

删除

d删除

删除第三行的内容

[root@yzq mnt]#sed -n '3d;p' txt
1 www.kgc.com
2 mail.kgc.com
4 linux.kgc.com
5 blog.kgc.com

删除3-5行的内容

[root@yzq mnt]#sed -n '3,5d;p' txt
1 www.kgc.com
2 mail.kgc.com

删除包含linux的行,第四行被删除

[root@yzq mnt]#sed -n '/linux/d;p' txt
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
5 blog.kgc.com

删除不包含linux的行,用!取反
!在指定内容的后面

[root@yzq mnt]#sed -n '/linux/!d;p' txt
4 linux.kgc.com

删除小写字母开头的行

[root@yzq mnt]#cat 2.txt
1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao
[root@yzq mnt]#sed -n '/^[a-z]/d;p' 2.txt 
1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com

删除数字开头的行

[root@yzq mnt]#sed -n '/^[0-9]/d;p' 2.txt 
baidu
google
jd
tmall
taobao

删除以m结尾的行

[root@yzq mnt]#sed -n '/m$/d;p' 2.txt 
baidu
google
jd
tmall
taobao

删除所有空行
注意: 若是删除重复的空行,即连续的空行只保留一个, 执行“ sed –e ‘/^KaTeX parse error: Expected group after '^' at position 6: /{n;/^̲/d}’test.txt”命令即可实现。其效果与“cat -s test.txt”相同,n 表示读下一行数据。

[root@yzq mnt]#sed -n '/^$/d;p' 2.txt 
1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao

s///替换删除

可以用替换来实现删除
将www替换为空格,即可达到删除的效果

[root@yzq mnt]#sed 's/www//' 2.txt 
1 .baidu.com
2 .google.com
3 .jd.com
4 .tmall.com
5 .taobao.com
baidu
google
jd
tmall
taobao

将每行第一个w删除(替换为空格)
/后面跟个数代表替换几个,/g代表全部替换

[root@yzq mnt]#sed 's/w//1' 2.txt 
1 ww.baidu.com
2 ww.google.com
3 ww.jd.com
4 ww.tmall.com
5 ww.taobao.com
baidu
google
jd
tmall
taobao
[root@yzq mnt]#sed 's/w//g' 2.txt 
1 .baidu.com
2 .google.com
3 .jd.com
4 .tmall.com
5 .taobao.com
baidu
google
jd
tmall
taobao

删除所有特殊字符

[root@yzq mnt]#sed 's/[^a-Z0-9]//g' 2.txt 
1wwwbaiducom
2wwwgooglecom
3wwwjdcom
4wwwtmallcom
5wwwtaobaocom
baidu
google
jd
tmall
taobao

添加

a:在行后添加

在第二行后面添加一行ww

[root@yzq mnt]#sed '2aww' 2.txt 
1 www.baidu.com
2 www.google.com
ww
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao

在第二行后添加多行 \n表示换行

[root@yzq mnt]#sed '2aw\nww' 2.txt 
1 www.baidu.com
2 www.google.com
w
ww
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao

在百度下面添加一行1

[root@yzq mnt]#sed '/baidu/a1' 2.txt 
1 www.baidu.com
1
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
1
google
jd
tmall
taobao

i在行前添加

i同a用法相同,不过i是在上面一行添加
在百度上一行添加1

[root@yzq mnt]#sed '/baidu/i1' 2.txt 
1
1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
1
baidu
google
jd
tmall
taobao

操作c整行替换

用c来替换,将选定行替换为指定内容
将第二行替换为google

[root@yzq mnt]#sed '2cgoogle' 2.txt 
1 www.baidu.com
google
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao

针对字符串替换

上面说过s///可以删除就是替换的原理,只不过是替换成空格
将全文baidu替换为qq

[root@yzq mnt]#sed 's/baidu/qq/g' 2.txt 
1 www.qq.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
qq
google
jd
tmall
taobao

s///最后一个/后面没有操作默认替换第一个

[root@yzq mnt]#sed 's/w/x/' 2.txt 
1 xww.baidu.com
2 xww.google.com
3 xww.jd.com
4 xww.tmall.com
5 xww.taobao.com
baidu
google
jd
tmall
taobao

全文注释

[root@yzq mnt]#sed 's/^/#/g' 2.txt 
#1 www.baidu.com
#2 www.google.com
#3 www.jd.com
#4 www.tmall.com
#5 www.taobao.com
#baidu
#google
#jd
#tmall
#taobao

指定某几行注释

[root@yzq mnt]#sed '1,3s/^/#/g' 2.txt 
#1 www.baidu.com
#2 www.google.com
#3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao

包含baidu的行注释

[root@yzq mnt]#sed '/baidu/s/^/#/g' 2.txt 
#1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
#baidu
google
jd
tmall
taobao

选项-i使修改的数据生效

以上的修改都是保存在sed临时的缓冲区中,并不是真实生效的,只有加上-i选项才能使修改生效

[root@yzq mnt]#sed '/baidu/s/^/#/g' 2.txt 
#1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
#baidu
google
jd
tmall
taobao
[root@yzq mnt]#cat 2.txt 
1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
baidu
google
jd
tmall
taobao
[root@yzq mnt]#sed -i '/baidu/s/^/#/g' 2.txt 
[root@yzq mnt]#cat 2.txt 
#1 www.baidu.com
2 www.google.com
3 www.jd.com
4 www.tmall.com
5 www.taobao.com
#baidu
google
jd
tmall
taobao

直接对文件修改有可能会出错,这时候可以使用-i.bak先备份再修改数据

[root@yzq mnt]#cat txt 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com
[root@yzq mnt]#sed -i.bak '2d' txt
[root@yzq mnt]#ls
1.txt   4.txt  Btxt  Dtxt                      shuzu
1.txtn  atxt   ctxt  expect.sh                 test
2.txt   Atxt   Ctxt  nginx.access.log-2021013  txt
3.txt   btxt   dtxt  passwd                    txt.bak
[root@yzq mnt]#cat txt
1 www.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com
[root@yzq mnt]#cat txt.bak 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

迁移符合条件的文本

迁移文本的参数
H: 复制到剪贴板;
g、G: 将剪贴板中的数据覆盖/追加至指定行;
w:保存为文件;
r:读取指定文件;
a:追加指定内容。
I,i 忽略大小写

把文本第一行复制到最后
G追加,$末尾

[root@yzq mnt]#sed '/www/{H};$G' txt.bak 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

1 www.kgc.com

把文本第一行剪切到最后
{;}用于多个操作,d:删除,$:末尾,g:覆盖

[root@yzq mnt]#sed '/www/{H;d};$g' txt.bak 
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com

1 www.kgc.com
[root@yzq mnt]#cat txt.bak 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

把1-3行剪切到第五行后面

[root@yzq mnt]#sed '1,3{H;d};5G' txt.bak 
4 linux.kgc.com
5 blog.kgc.com

1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com

将包含www的行保存到www文件中

[root@yzq mnt]#sed '/www/w www' txt.bak 
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com
[root@yzq mnt]#cat www 
1 www.kgc.com

从www文件中读取文件到包含www的行下面
将www文件中的内容输出到包含www的行的下面

[root@yzq mnt]#sed '/www/r www' txt.bak 
1 www.kgc.com
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com

sed分组

sed使用扩展正则分组提取网卡中IP地址

-r使用扩展正则,使用s/ / /将一行文件分组,而()中的成组,\1代表提取第一组
s/.inet (.) net.*/\1/p中.*inet表示需要提取IP之前的字符,inet前面的空格不知道几个,直接用.*代替,
而IP之前的字符为netmask开头,我们也不需要知道具体,只需用net.*代表IP之后的字符,而要提取的内容为()中的,我们只需用.*匹配即可,分割以空格隔开,只有()中的为组,这里我们提取第一组 \1表示的是第一组,即()中的字符,最后p打印出来即可

[root@yzq mnt]#ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.28.10  netmask 255.255.255.0  broadcast 192.168.28.255
        inet6 fe80::c5af:9d75:a8f6:7c70  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:c6:78:5e  txqueuelen 1000  (Ethernet)
        RX packets 22628  bytes 20936910 (19.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8362  bytes 690252 (674.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@yzq mnt]#ifconfig ens33 | sed -nr 's/.*inet (.*) net.*/\1/p'
192.168.28.10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值