Linux文本三剑客之sed编辑器(永远温柔永远清醒)
目录
前言
一、特点及格式
二、sed核心应用
2.1 sed-查找打印p
2.2 sed-删除d
2.3 sed-增加air
2.4 sed-替换scy
2.5 sed-剪切H-粘贴G
总结
前言
我们将/etc/passwd文件拷贝到/data下做实验,以免影响系统
一、特点及格式
- sed stream editor 流编辑器,sed把处理的内容(文件),当做是水,源源不断的进行处理,知道文件末尾
-
sed编辑器可以根据命令来处理数据流中的数据,这些命令从命令行中输入或者存储在一个命令文本文件中,可以理解为脚本
- sed常用选项
选项 | 功能 |
-r | 使用了扩展正则需要 |
-e或--expression= | 表示用指定命令来处理输入的文本文件,只有一个操作命令时可以省略,一般在执行多个操作命令使用 |
-f或--file= | 表示用指定的脚本文件来处理输入的文本文件 |
-h或者--help | 显示帮助 |
-n、--quiet或silent | 禁止sed编辑器输出,但可以与p命令一起使用完成输出 |
-i | 直接修改目标文本文件 |
- sed命令的核心功能:增删改查
功能 | 含义 |
s | 替换substitute sub |
p | 显示print |
n | 把当前操作移动到下一行操作 |
d | 删除delete |
ai | 增加a/i |
c | 整行替换 |
y |
对应字符转换,转换前后的字符长度必须相同 |
l(小写L) |
打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t) |
sed的工作流程主要包括读取、执行和显示三个过程:
- 读取: sed从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间, pattern space)。
- 执行:默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行。
- 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:
默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出
sed是逐行读取执行显示的,如果文件很大效率会很低,影响IO性能,可以使用“cat 文件 | sed split拆分若干小文件再处理”
命令格式:sed 参数 '操作' 文件1 文件2sed -e 'n{操作1操作2...}' 文件1 文件2 ...同时处理多个操作需要分行处理,并且带上行号n,否则会全部显示
二、sed核心应用
2.1 sed-查找打印p
- 查找
查找格式 | 含义 |
'2p' | 指定行号进行查找 |
'1,5p' | 指定行号范围进行查找 |
'/root/p' | 类似于grep过滤,//里面可以写正则 |
'/10:00/,/11:00/p' | 表示范围的过滤,多用于按照时间范围找日志 |
1,/root/p | 混合(从第一行到匹配到root的行) |
#打印内容[root@localhost data]# sed -e 'p' users.txt 1,zhangsan1,zhangsan2,lisi2,lisi3,wangwu3,wangwu4,zhaoliu4,zhaoliu5,qianqi5,qianqi6,zhuba6,zhuba[root@localhost data]# sed 'p' users.txt 1,zhangsan1,zhangsan2,lisi2,lisi3,wangwu3,wangwu4,zhaoliu4,zhaoliu5,qianqi5,qianqi6,zhuba6,zhuba#查找第二行内容[root@localhost data]# sed -n '2p' passwdbin:x:1:1:bin:/bin:/sbin/nologin#查找第1到3行内容[root@localhost data]# sed -n '1,3p' passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin#查看第一行和他后面的三行内容[root@localhost data]# sed -n '1,+3p' passwd root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologin#查找第38行到最后一行的内容[root@localhost data]# sed -n '38,$p' passwdpostfix:x:89:89::/var/spool/postfix:/sbin/nologinsshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologintcpdump:x:72:72::/:/sbin/nologinzhangsan:x:1000:1000:zhangsan:/home/zhangsan:/bin/bashapache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin[root@localhost data]# #显示1-5行[root@localhost data]# sed -e '5q' passwd root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin#打印行号,不打印内容[root@localhost data]# sed -n '=' users.txt 123456#显示非打印字符[root@localhost data]# sed -n 'l' users.txt 1,zhangsan$2,lisi$3,wangwu$4,zhaoliu$5,qianqi$6,zhuba$#同时处理多条操作[root@localhost data]# sed -n -e '=' -e 'p' users.txt 11,zhangsan22,lisi33,wangwu44,zhaoliu55,qianqi66,zhuba[root@localhost data]# sed -n -e '=;p' users.txt 11,zhangsan22,lisi33,wangwu44,zhaoliu55,qianqi66,zhuba[root@localhost data]# sed -n '> => p> ' users.txt11,zhangsan22,lisi33,wangwu44,zhaoliu55,qianqi66,zhuba#显示奇偶行[root@localhost data]# sed -n 'p;n' users.txt 1,zhangsan3,wangwu5,qianqi[root@localhost data]# sed -n 'n;p' users.txt 2,lisi4,zhaoliu6,zhuba
每行出现了两次,一次是p命令打印的,一次是不加-n,sed命令的显示过程
首先sed命令按行读入,然后打印,接着跳到下一行,此时没有操作了,第一次sed操作完成;
开始读入三行
......
- 过滤
#查找含有root的行[root@localhost data]# sed -n '/root/p' passwd root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin[root@localhost data]# #查找包含bash或者root的行[root@localhost data]# sed -nr '/bash|root/p' passwd root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologinzhangsan:x:1000:1000:zhangsan:/home/zhangsan:/bin/bash#查找数字出现三次的行,使用扩展正则需要加上-r参数[root@localhost data]# sed -n '/[0-9]{3}/p' passwd [root@localhost data]# sed -nr '/[0-9]{3}/p' passwd games:x:12:100:games:/usr/games:/sbin/nologinsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologinpolkitd:x:999:997:User for polkitd:/:/sbin/nologinabrt:x:173:173::/etc/abrt:/sbin/nologinlibstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologincolord:x:997:994:User for colord:/var/lib/colord:/sbin/nologinsaslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologinsetroubleshoot:x:995:993::/var/lib/setroubleshoot:/sbin/nologinrtkit:x:172:172:RealtimeKit:/proc:/sbin/nologinpulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologinqemu:x:107:107:qemu user:/:/sbin/nologinchrony:x:994:990::/var/lib/chrony:/sbin/nologinusbmuxd:x:113:113:usbmuxd user:/:/sbin/nologingeoclue:x:993:988:User for geoclue:/var/lib/geoclue:/sbin/nologinsssd:x:992:987:User for sssd:/:/sbin/nologinnfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologingnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologinzhangsan:x:1000:1000:zhangsan:/home/zhangsan:/bin/bash[root@localhost data]#
表示范围过滤的时候,如果结尾的内容匹配不到就会一直显示到最后一行
2.2 sed-删除d
删除格式 | |
'2d' | 指定行号进行删除 |
'1,5d' | 指定行号范围进行删除 |
'/root/d' | 类似于grep过滤,//里面可以写正则 |
'/10:00/,/11:00/d' | 表示范围的过滤,多用于按照时间删除找日志 |
1,/root/d | 混合(从第一行到匹配到root的行) |
[root@localhost data]# cat users.txt 1,zhangsan2,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba#删除2-3行[root@localhost data]# sed '2,3d' users.txt 1,zhangsan4,zhaoliu5,qianqi6,zhuba[root@localhost data]# #删除匹配到zhangsan的行,整行删除[root@localhost data]# sed '/zhangsan/d' users.txt 2,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba[root@localhost data]# #删除第一个包含字符串2的行到第一个包含字符串3的行[root@localhost data]# sed '/2/,/3/d' users.txt 1,zhangsan4,zhaoliu5,qianqi6,zhuba
这里的删除其实是不显示,原来的文件并没有删除
sed会读取每行的内容,从第一行位置打开删除功能,到第二个位置删完后关闭删除功能,如果匹配不到第二个位置就删到文件末尾
- 企业案例:删除文件中的空行和包含井号的行
egrep -v '^$|#' /etc/ssh/sshd_config#-v 取反显示sed -r '/^$|#/d' /etc/ssh/sshd_config#-r 从文件中读取输入行(使用了正则需要加上-r)sed -nr '/^$|#/!p' /etc/ssh/sshd_config#!的妙用,需要空行和井号的行不显示
仅仅删除空行,下面这条命令也可以
cat /etc/ssh/sshd_config |tr -s "\n"
2.3 sed-增加air
命令 | 含义 |
a | append追加,向指定的每一行追加内容(行后面)>> |
i |
insert插入,向指定的每一行插入内容(行前面) |
r | 在行后增加文件内容 |
[root@localhost data]# cat users.txt 1,zhangsan2,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba[root@localhost data]# sed '1a zhangsan996' users.txt 1,zhangsanzhangsan9962,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba[root@localhost data]# sed '1i zhangsan996' users.txt zhangsan9961,zhangsan2,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba[root@localhost data]# sed '1r ip.txt' users.txt 1,zhangsan192.168.109.1192.168.109.2192.168.109.3192.168.109.4192.168.109.52,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba
- 企业案例:向文件中追加多行内容
向config里面追加UseDNS noGSSAPIAUTCATION noPermitRootLogin no#方法一[root@localhost data]# touch config[root@localhost data]# cat >>config< UseDNS no> GSSAPIAUTCATION no> PermitRootLogin no> EOF#方法二[root@localhost data]# sed -i '$a UseDNS no\nGSSAPIAUTCATION no\nPermitRootLogin no' config
2.4 sed-替换scy
替换格式 |
sg |
s///g |
sAAAg |
替换标记 | 含义 |
数字 | 表明新字符串将替换第几处匹配的地方 |
g | 表明新字符串将会替换所有匹配的地方 |
p | 打印与替换命令匹配的行,与-n一起使用 |
w文件 | 将替换的结果写到文件中 |
s | 字符串替换 |
c | 整行替换 |
y | 字符转换,转换前后的字符长度必须相同 |
- 分隔符不唯一,只有三个相同就行;
- 前两个分隔符之间支持正则;
- 不加g则是替换每一行第一个被匹配到的内容,g是全局的意思;
- 替换操作类似vim的末行模式;
#每一行的数字替换为空[root@localhost data]# sed 's/[0-9]//g' users.txt ,zhangsan,lisi,wangwu,zhaoliu,qianqi,zhuba#root替换为admin[root@localhost data]# sed -n 's/root/admin/p' passwd admin:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/admin:/sbin/nologin[root@localhost data]# sed -n 's/root/admin/2p' passwd root:x:0:0:admin:/root:/bin/bash#删除前面的所有0[root@localhost data]# echo 000000001010|sed 's/^0*//'1010#给1-10行加上注释[root@localhost data]# sed '1,10 s/^/#/' 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......#将所有root开头的行注释[root@localhost data]# sed -n 's/^root/#root/p' passwd #root:x:0:0:root:/root:/bin/bash[root@localhost data]# sed -n '/^root/ s/^/#/p' passwd #root:x:0:0:root:/root:/bin/bash#注释fstab文件中的swap行[root@localhost data]# sed -n '/swap/ s/^/#/p' /etc/fstab #/dev/mapper/centos-swap swap swap defaults 0 0[root@localhost data]# sed -n 's/.*swap.*/#&/p' /etc/fstab #/dev/mapper/centos-swap swap swap defaults 0 0[root@localhost data]#
- 脚本
#使用脚本执行sed命令[root@localhost data]# vim script.sed1,10 s/^/#/#1-10行注释/root/ s/$/#/#包括root的行后面加上井号
如同只用了多次-e操作
- 保存至文件
#保存替换的内容到新的文件中[root@localhost data]# sed -n 's/root/admin/gp' passwd >out1.txt[root@localhost data]# cat out1.txt admin:x:0:0:admin:/admin:/bin/bashoperator:x:11:0:operator:/admin:/sbin/nologin[root@localhost data]# sed -n 's/root/admin/w out2.txt' passwd [root@localhost data]# cat out2.txt admin:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/admin:/sbin/nologin[root@localhost data]#
- 思考
sed 's9\945\9\99\98\939g' 1.txt #这行命令是谁替换谁9\945\9\99\98\939#前面说过,分隔符是三个一样的字符就可以,可以看出分隔符是9而\是转义字符#去掉三个没有转义的9就是下面的样子94599 9893#所以是94599替换成9893
- 后向使用,反向使用(先保护再使用)
#要实现这两种内容的转变[root@localhost data]# echo 123456123456[root@localhost data]# echo ''#前后交换[root@localhost data]# echo old_new |sed -r 's#(^.*)_(.*$)#\2_\1#g'new_old
(old)_(new)
\1_\2
- c/y
[root@localhost data]# sed '1c zhangsan996' users.txt zhangsan9962,lisi3,wangwu4,zhaoliu5,qianqi6,zhuba#使用y转换[root@localhost data]# sed 'y/zhangsan/zzzzzzzz/' users.txt 1,zzzzzzzz2,lizi3,wzzzwu4,zzzoliu5,qizzqi6,zzubz[root@localhost data]# sed 'y/zhangsan/zzzzzzz/' users.txt sed:-e 表达式 #1,字符 19:“y”命令的字符串长度不同[root@localhost data]# #使用tr替换[root@localhost data]# cat users.txt |tr 'zhangsan' 'zzzzzzzz'1,zzzzzzzz2,lizi3,wzzzwu4,zzzoliu5,qizzqi6,zzubz[root@localhost data]# cat users.txt |tr 'zhangsan' 'zzzz'1,zzzzzzzz2,lizi3,wzzzwu4,zzzoliu5,qizzqi6,zzubz
2.5 sed-剪切H-粘贴G
#将1-3行剪切并粘贴到最后[root@localhost data]# sed '1,3 {H;d};$G' users.txt 4,zhaoliu5,qianqi6,zhuba1,zhangsan2,lisi3,wangwu
总结
sed执行多条命令的方式:
sed -n -e '命令1' -e '命令2' 文件sed -n -e '命令1;命令2' 文件sed -n '命令1命令2......' 文件
sed对指定行操作:
- 以数字形式表示行区间
- 用字符串来过滤行
s/OLD/NEW/2 代表对每行第二个匹配到的字符串进行替换
g 代表对每行所有能匹配到的字符进行替换
p 可以结合-n 选项只打印替换的行内容
w 可以把替换的行内容保存到指定的文件中
n,m s/OLD/NEW/
/字符串+正则/ s/OLD/NEW
s/^/添加的字符/ 行首添加内容
s/$/添加的字符/ 行尾添加内容
sed -f 文件 可以在文件中定义多条操作规则
sed替换命令的字符串分隔符,就看s后面跟的字符,3个分隔符要保持一致,如果遇到跟分隔符相同的字符则需要使用\来转义
sed -i 可以直接修改文件内容,操作前建议先验证命令和备份目标文件
增删改查
删d
改s(字符串替换) c(整行替换) y(对应字符串替换,效率类似tr)
查p
增 a(在行后)i(在行前)r(在行后读入文件内容)
复制粘贴 H;G