华子目录
sed概念
- sed是一个非交互式的文本编辑器,是将一系列的编辑命令应用于一批文本的理想工具,可以对来自文本文件以及标准输入的文本进行编辑。其中,标准输入可以是来自键盘、文件重定向、字符串、变量或者是管道的文本
sed
命令拥有非交互式和高效的特点,可以为用户节约大量的时间- Vim 采用的是交互式文本编辑模式,可以用键盘命令来交互性地插入、删除或替换数据中的文本。但 sed命令不同,它采用的是流编辑模式,最明显的特点是,在 sed 处理数据之前,需要预先提供一组规则,
sed
会按照此规则来编辑数据
工作原理
-
模式空间
pattern space
:sed
在内存
里开辟模式空间
,处理文件的每个输入行,最多8192字节 -
保留空间
holding space
:sed
在内存
里开辟保留空间
,保存已经处理过的输入行,最多8192字节 -
原理:sed 的工作流程主要包括读取、执行和显示三个过程:
- 读取:
sed
从输入流(文件、管道、标准输入
)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space
)。 - 执行:默认情况下,所有的
sed
命令都在模式空间
中顺序地执行,除非指定了行的地址
,否则sed
命令 将会在所有的行
上依次执行
。 - 显示:发送
修改后的内容
到输出流
。在发送数据后,模式空间
将会被清空 - 重复上述过程,直到将文件中所有数据处理完毕
- 读取:
-
注意:默认情况下所有的
sed
命令都是在模式空间
内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出
基本语法
格式
[root@server ~]# sed 参数 '[定位符]' '操作' 文件名
定位符
和操作
一般是连用
的(在一个单引号
中)
参数
参数 | 说明 |
---|---|
-n | 安静模式 ,不输出模式空间中的内容,在一般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动作 |
--help | 显示帮助 |
--version | 显示版本 |
-{} | 可组合多个命令,以分号 隔开 |
定位符
- 用于使用
数字
指定处理的行区间
,或者使用正则
进行过滤 - 表示方法
地址定界 | 作用 |
---|---|
1,5 | 对文件的1-5行 内容进行处理 |
2,$ | 对文件的2到最后一行 内容进行处理 |
1,+3 | 对文件第1行 以及之后的3行 内容进行处理 |
1~2 | 对文件的1,3,5,7,…… 的行内容进行处理 |
/正则表达式/ | 对任何能够被正则表达式 匹配到的行进行处理 |
操作
标识 | 说明 |
---|---|
S | 替换,替换指定字符,一般搭配正则表达式 |
d | 删除,删除选定的行。 |
p | 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“ -n”选项一起使用 。 |
= | 打印行号。 |
a | 增加(append),a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行) |
i | 插入(insert),i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行) |
c | 行替换,指定行中的所有内容,替换成该选项后面的字符串。 |
y | 字符转换,转换前后的字符长度必须相同。 |
l | 打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t) |
! | 指定行以外 的所有行 |
& | 代表匹配到的内容 |
1.输出文本
范例文本
[root@server ~]# sed -n 'p' sed1.txt #全文打印,-n只有经过处理的才会被打印,p表示打印
[root@server ~]# sed -n '=;p' sed1.txt # 全文打印并显示行号,分号用来分割动作
[root@server ~]# sed -n -e '=;p' sed1.txt #使用-e效果同上
[root@server ~]# sed -n -e '=' -e 'p' sed1.txt #使用-e效果同上
[root@server ~]# sed -n 'l' sed1.txt #全文显示并输出控制字符(比如结束符$、制表符\t)
[root@server ~]# sed -n ' #全文打印,交互模式
> =
> p
> ' sed1.txt
注:不加-n
会重复显示
,不加p
无法打印
,所以-n和p
连用使用
定址符和操作符连用
[root@server ~]# sed -n '1p' sed1.txt #打印第一行
[root@server ~]# sed -n '4,6p' sed1.txt #打印4-6行
[root@server ~]# sed -n '3,12p' sed1.txt #打印3-12行,超行范围只显示实际内容
[root@server ~]# sed -n '7,$p' sed1.txt #打印7到最后一行
[root@server ~]# sed -n '$p' sed1.txt #打印最后一行
[root@server ~]# sed -n '2~2p' sed1.txt #打印偶数行
[root@server ~]# sed -n '1~2p' sed1.txt #打印奇数行
[root@server ~]# sed -n '4p;6p;8p' sed1.txt #打印4、6、8行
[root@server ~]# sed -n -e '4p' -e '6p' -e '8p' sed1.txt #打印4、6、8行
[root@server ~]# sed -n '1,+5p' sed1.txt #打印第1行及其后5行
[root@server ~]# sed -n '1!p' sed1.txt #打印除了第1行的其他行
[root@server ~]# sed -n '2,3!p' sed1.txt #打印除了2-3行的剩余行
[root@server ~]# sed -n '1~2!p' sed1.txt #打印偶数行
搭配正则使用
正则表达式
写在/ /
中间
[root@server ~]# sed -n '/^f/p' sed1.txt # 打印f开头的行
[root@server ~]# sed -n '/t/p' sed1.txt # 检索包含t的行
[root@server ~]# sed -n '/^t/p ; /^f/p' sed1.txt # 检索包含t开头或者包含f开头的行信息
[root@server ~]# sed -n -e '/^t/p' -e '/^f/p' sed1.txt # 检索包含t开头或者包含f开头的行信息
[root@server ~]# sed -n '2,/five/p' sed1.txt #检索第2行到five所在行
[root@server ~]# sed -n '/n$/p' sed1.txt #检索n结尾的行信息
规定语法
[root@server ~]# sed -n 'n;p' sed1.txt # 检索偶数行
[root@server ~]# sed -n 'p;n' sed1.txt # 检索奇数行
[root@server ~]# sed -n '$=' sed1.txt # 打印文本的总行数
2.文本替换
范例文件
/etc/passwd
[root@server ~]# cp /etc/passwd ~/ps
[root@server ~]# cat ps
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
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
colord:x:997:993:User for colord:/var/lib/colord:/sbin/nologin
clevis:x:996:992:Clevis Decryption Framework unprivileged user:/var/cache/clevis:/usr/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
sssd:x:995:991:User for sssd:/:/sbin/nologin
geoclue:x:994:990:User for geoclue:/var/lib/geoclue:/sbin/nologin
libstoragemgmt:x:993:989:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
setroubleshoot:x:992:988:SELinux troubleshoot server:/var/lib/setroubleshoot:/sbin/nologin
pipewire:x:991:986:PipeWire System Daemon:/var/run/pipewire:/sbin/nologin
flatpak:x:990:985:User for flatpak system helper:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
cockpit-ws:x:989:984:User for cockpit web service:/nonexisting:/sbin/nologin
cockpit-wsinstance:x:988:983:User for cockpit-ws instances:/nonexisting:/sbin/nologin
gnome-initial-setup:x:987:982::/run/gnome-initial-setup/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/usr/share/empty.sshd:/sbin/nologin
chrony:x:986:981::/var/lib/chrony:/sbin/nologin
dnsmasq:x:985:980:Dnsmasq DHCP and DNS server:/var/lib/dnsmasq:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
systemd-oom:x:978:978:systemd Userspace OOM Killer:/:/usr/sbin/nologin
redhat:x:1000:1000::/home/redhat:/bin/bash
格式
[root@server ~]# sed 参数 '行范围s/旧字符串/新字符串/替换标记' 文件名
注:旧字符串
可以是正则表达式
行范围
:使用数字
表示,即对第几行到第几行
进行替换处理
,若省略
则表示进行全文处理
s
: 表示替换动作
替换标记
数字
:使用1-512
之间的数字,表示指定需要替换的字符串
出现第几次
才进行替换
g
:对数据中所有匹配
到的内容
进行替换
,若省略g
则只会对第一次
匹配的内容
进行替换
p
:替换
成功立刻打印
,一般与-n
一起使用w 文件名
: 将缓冲区的内容
写入到指定文件
中&
: 使用正则表达式
匹配的内容
进行替换
\
:转义符
,若有特殊符号
或路径
则需要转义
示例
[root@server ~]# sed -n 's/root/boot/gp' ~/ps #全文替换包含root为boot
[root@server ~]# sed 's/root/boot/g' ~/ps # 不加-n及动作p会显示未变化的和变化的行信息(所有行)
[root@server ~]# sed -n 's/root/admin/2p' ~/ps #将每一行第2次出现的root替换为admin
[root@server ~]# sed -n 's/root/admin/p' ~/ps #不加g,默认将每一行第1个root替换为admin
[root@server ~]# sed -n '4s/adm/root/gp' ~/ps #将第4行的adm全部替换为root
# 注意:替换的内容及新字符串中有路径分隔符,为了与sed的斜杠分隔符区分开来,需要对路径分隔符/之前增加 转义符\
[root@server ~]# sed -n 's/\/sbin\/nologin/\/bin\/bash/gp' ~/ps
# 注意:若替换内容及新内容中有路径/符号,可以将sed自带的三个/更换成#
[root@server ~]# sed -n 's#/sbin/nologin#/bin/bash#gp' ~/ps
# 注意:由于上例,则sed自带三个/可以更换成#
[root@server ~]# sed -n 's#root#boot#gp' ~/ps
# 注意:若替换内容就是#时,sed自带三个/不能更换为#
# 将最后一行的所有:替换为@
[root@server ~]# sed -n '$s/:/@/gp' ~/ps
&
示例
[root@server ~]# sed -n 's/^/#/p' ~/ps #全文增加注释
#查找结果中部分内容插入新内容
[root@server ~]# sed -n 's/SSH/&@/p' ~/ps
#正则搭配使用
[root@server ~]# sed -n 's/.edhat/#/gp' ~/ps
#在SSH左侧插入@
[root@server ~]# sed -n 's/SSH/@&/p' ps
# 所有的行首及行尾添加@
[root@server ~]# sed 's/^/@/g ; s/$/@/g' ~/ps
#文本第一行之前插入空白行
[root@server ~]# sed '1s/^/\n/' ~/ps
# 最后一行插如空白行
[root@server ~]# sed '$s/$/\n/' ~/ps
\u
大写字母
# 全文所有小写字母改为大写字母,\u表示大写字母,不能写[A-Z]
[root@server ~]# sed 's/[a-z]/\u&/g' ~/ps
\L
小写字母
# 全文所有大写字母改为小写字母,\L为小写字母
[root@server ~]# sed 's/[A-Z]/\L&/g' ~/ps
\b
确定单词边界
#单词首字母大写,\b确定单词边界即第一个字母
[root@server ~]# sed 's/\b[a-z]/\u&/g' ~/ps
配置实例
# 开启或关闭selinux
[root@server ~]# sed -i 's/SELINUX=disabled/SELINUX=enforcing/' /etc/selinux/config
或者
[root@server ~]# sed -i '22s/disabled/enforcing/' /etc/selinux/config
# httpd网页目录替换
[root@server ~]# yum install httpd -y
#mobaxterm上传网页数据
[root@server ~]# sed -i -e '124s/\/var\/www\/html/\/zy/' -e '129s/\/var\/www/\/zy/' /etc/httpd/conf/httpd.conf
[root@server ~]# systemctl start httpd
# 浏览器测试
# 修改bind
[root@server ~]# sed -i -e 's/127.0.0.1/any/p' -e 's/localhost/any/' /etc/named.conf
# 支持管道符即输出重定向
[root@server ~]# echo "china" | sed 's/[a-z]/\u&/'
China
[root@server ~]# echo "china" | sed 's/[a-z]/\u&/g'
CHINA
[root@server ~]# echo "china" | sed 's/[a-z]/\u&/g' > t1.txt
[root@server ~]# cat t1.txt
CHINA
使用替换实现删除
#将全文root删除
[root@server ~]# sed -n 's/root//gp' ~/ps
[root@server ~]# sed -n 's/root/''/gp' ~/ps #本质
#删除全文注释
[root@server ~]# sed -n 's/^#//p' /etc/sos/sos.conf
#删除每一行第一个字符,^.表示第一个字符
[root@server ~]# sed -n 's/^.//p' ~/ps
#删除每行最后一个字符
[root@server ~]# sed -n 's/.$//p' ~/ps
#删除第5-10的所有的数字
[root@server ~]# sed -n '5,10s/[0-9]//gp' ~/ps
#删除所有特殊字符(除了数字、字母)另存为到文件t1.txt
[root@server ~]# sed 's/[^(a-z)(A-Z)(0-9)]//gw t1.txt' ~/ps #[^]表示取反
[root@server ~]# cat t1.txt
3.删除文本
- d操作用于删除文本的特定行,会删除指定的所有内容,则使用该命令必须特别小心,若
忘记指定处理行的话会删除所有内容
,也不会有任何输出
[root@server ~]# sed -i 'd' ps #清空ps文本内容
[root@server ~]# cat ps
[root@server ~]#
示例
# 准备示例文件
[root@server ~]# cp /etc/sos/sos.conf ~/sos.conf
[root@server ~]# ls
公共 视频 文档 音乐 anaconda-ks.cfg sed1.txt
模板 图片 下载 桌面 ps sos.conf
# 删除第1行
[root@server ~]# sed '1d' sos.conf
[root@server ~]# line_number=2
[root@server ~]# sed "${line_number}d" sos.conf # 变量作为行号,需要使用双引号
[root@server ~]# sed '/^$/d' sos.conf # 删除全文的空白行
[root@server ~]# sed '/Options/d' sos.conf # 删除Options的所在行
# 多个删除条件的写法:
[root@server ~]# sed -e '/Options/d' -e '/options/d' sos.conf
[root@server ~]# sed '/Options/d ; /options/d' sos.conf
[root@server ~]# sed -e '/Options/d' sos.conf | sed '/options/d' sos.conf
#删除包含3到包含5的所有行
[root@server ~]# sed '/3/,/5/d' sos.conf
#删除[开头的行,需要转义
[root@server ~]# sed '/^\[/d' sos.conf
#删除注释行,但是为整行删除
[root@server ~]# sed '/^#/d' sos.conf
注意:删除时
先不要加-i
写回源文件,否则无法恢复
4.插入文本
- 使用
a
动作在文本
最后追加一行
,使用i
动作在指定行前
插入一行
,两者格式相同
格式
[root@server ~]# sed '行范围a(或i)\新文本' 文件名
示例
#在hosts文本最后,追加A记录
[root@server ~]# sed -i '$a\192.168.48.130 www.openlab.com' /etc/hosts
[root@server ~]# cat /etc/hosts
#在hosts第3行插入A记录
[root@server ~]# sed -i '3i\192.168.48.131 www.openlab.com' /etc/hosts
[root@server ~]# cat /etc/hosts
[root@server ~]# sed -i '/131/i\192.168.48.132 www.openlab.com' /etc/hosts
[root@server ~]# cat /etc/hosts
注意
sed
命令是基于数据流
的处理命令
,若文件内容为空
,无法插入数据
[root@server ~]# touch t2.txt
[root@server ~]# cat t2.txt
[root@server ~]# sed -i '$a\xiaoming 18 98.5' t2.txt
[root@server ~]# cat t2.txt
[root@server ~]# cat t2.txt
[root@server ~]# sed -i '1i\xiaoming 18 98.5' t2.txt
[root@server ~]# cat t2.txt