> 文档中心 > Linux文本三剑客之sed编辑器(永远温柔永远清醒)

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对指定行操作:

  1. 以数字形式表示行区间
  2. 用字符串来过滤行

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