简介
-
sed工具式:
- stream EDitor,流式编辑器
- 非交互式,基于模式模式匹配过滤及修改文本
- 逐行处理(特点),并将结果输出到屏幕中
- 可以实现对文本的输出,删除,替换,复制,剪切,到处,等各种操作 -
命令格式
- 主要用法:
- 格式1:前置命令 | sed [选项] ‘编辑指令’
- 格式2:sed [ 选项 ] ‘编辑指令’ 文件……
- 主要用法:
编辑指令 —> [定址符号]处理动作
定址符 --> [地址1地址2]]
-
格式解析
- 常见命令选项
- -n : 屏蔽默认输出(全部文本)
- -i : 直接修改文本内容
- -r : 启用扩展的正则表达式,若与其他选项一起使用,应作为首个选项 - 条件,可以式行号或者/正则/
- 行号可以使用当个数字表示单行
- 或者3,5表示连续的多行
- 省略条件,则默认逐行处理全部文本
- 匹配正则时,需要使用 #
- 常见命令选项
-
基本的处理动作
- 常用动作指令
操作符 | 用途 | 指示示例 |
---|---|---|
p | 打印行 | 2,4p 输出第2、3、5、4行 |
d | 删除行 | 2p;4p 输出第2、4行 |
s | 字符串替换 | s/old/new/(将每一行的第一个old替换成new)、 s/old/new/3(将每一行的第三个old替换成new)、s/old/new/g(将每一行的所有old替换成new) |
- sed [选项] ‘条件指令’ 文件… …
- 支持正则表达式:
[root@room13pc37 ~]#head -5 /etc/passwd > /root/1.txt #先准备一份练习文件
[root@room13pc37 ~]# cat 1.txt
root:x:0:0:root:/root:/bin/bash
...#省略
#先直接使用动作指令
#用sed显示文本的内容:
[root@room13pc37 ~]# sed 'p' 1.txt #直接使用动作指令 “p”显示1.txt的文本内容
root:x:0:0:root:/root:/bin/bash
....#省略
--------------------------
#注意:我们会发现我们的1.txt文件只有5行内容,但是我们使用sed工具输出,它把文本内容输出两次。
#这是应为sed的特点是:逐行处理,显示到屏幕当中,所以在我们用“p”命令输出1.txt文本内容时间,默认还会显示多一次,对此我们可以使用-n来取消默认输出。
---------------------------
[root@room13pc37 ~]# sed -n 'p' 1.txt #取消默认输出
root:x:0:0:root:/root:/bin/bash
...#省略
[root@room13pc37 ~]# sed -n '1,4p' 1.txt #输出1到4行的内容
root:x:0:0:root:/root:/bin/bash
...
[root@room13pc37 ~]# sed -n "1p;3p" 1.txt #输出1、3行的内容
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@room13pc37 ~]# sed -n '2,+2p' 1.txt #大家需要注意,+2p是指前面输出行的后面2行的内容。需要注意前面输出的是第2行的内容,所以一共输出的是3行内容
bin:x:1:1:bin:/bin:/sbin/nologin #第2行的内容
daemon:x:2:2:daemon:/sbin:/sbin/nologin # 第2行后面的2行内容
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@room13pc37 ~]# sed -n "1~2p" 1.txt #输出1,3,5行的内容,1~2是表示:从第1行开始输出,间隔输出两行。同理 2~2p :输出2,4,6行的文本内容。
root:x:0:0:root:/root:/bin/bash #第1行内容
daemon:x:2:2:daemon:/sbin:/sbin/nologin #第3行内容
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin #第5行内容
[root@room13pc37 ~]# head -5 /etc/passwd > /root/3.txt | sed -n 'p' 3.txt
root:x:0:0:root:/root:/bin/bash
...#省略
[root@room13pc37 ~]#
- 使用正则表达式做定址符
[root@room13pc37 ~]# sed -n '/root/p' /etc/passwd #搜索包含root的行
[root@room13pc37 ~]# sed -n '/^root/p' /etc/passwd #搜索以root开头的行
[root@room13pc37 ~]# sed -n '/bash$/p' /etc/passwd #搜索以bash结尾的行
-
sed工具的p、d、s操作指令案例集合
- sed工具的p指令案例集锦(自己提前生成一个test.txt文件)
[root@room13pc37 shell_test]# sed -n 'p' test.txt #输出所有行,等同于cat test.txt [root@room13pc37 shell_test]# sed -n '4p' test.txt #输出第4行 [root@room13pc37 shell_test]# sed -n '4,7p' test.txt #输出第4~7行 [root@room13pc37 shell_test]# sed -n '4,+10p' test.txt #输出第4行及其后的10行内容 [root@room13pc37 shell_test]# sed -n '/^bin/p' test.txt #输出以bin开头的行 [root@room13pc37 shell_test]# sed -n '=' test.txt #输出文件的所有行号 [root@room13pc37 shell_test]# sed -n '$=' test.txt #输出文件的最后一行的行号 [root@room13pc37 shell_test]# sed -n '/root/=' tset_sed.s.txt #说出文件包含root的行数
- sed工具的d指令案例集锦(提前生成一个test.txt文件)
[root@room13pc37 shell_test]# sed '3,5d' test.txt #删除第3~5行 [root@room13pc37 shell_test]# sed '/xml/d' test.txt #删除所有包含xml的行 [root@room13pc37 shell_test]# sed '/xml/!d' test.txt #删除不包含xml的行,!符号表示取反 [root@room13pc37 shell_test]# sed '/^install/d' test.txt #删除以install开头的行 [root@room13pc37 shell_test]# sed '$d' test.txt #删除文件的最后一行 [root@room13pc37 shell_test]# sed '/^$/d' test.txt #删除所有空行
- sed命令的s替换基本功能(s/旧内容/新内容/选项)
[root@room13pc37 shell_test]#vim test.txt #新建素材文件 2017 2011 2018 2017 2017 2024 2017 2017 2017 [root@room13pc37 shell_test]#sed 's/2017/xxxx/' test.txt #把当前所有行的第一个2017都替换 [root@room13pc37 shell_test]#sed 's/2017/xxxx/g' test.txt #替换的是的当前行的所有 [root@room13pc37 shell_test]#sed 's/2017/xxxx/2' test.txt #替换的是当前行的的第二个2017 [root@room13pc37 shell_test]#sed 's/2017#2' test.txt #把所有行中的第二2017替换成 空,相当于删除。 [root@room13pc37 shell_test]#sed -n 's/2017/xxxx/p' test.txt #把所有行的第一个2017都替换调,同时显示所替换的行结果。 [root@room13pc37 shell_test]# head /etc/passwd > tset_sed.s.txt #素材文件 [root@room13pc37 shell_test]# sed -n 's/^root/xxx/p' tset_sed.s.txt #把root开头所在的行给替换 xxx:x:0:0:root:/root:/bin/bash [root@room13pc37 shell_test]# sed -n 's//bin/bash//bin/sh/p' tset_sed.s.txt # / 过多系统无法识别,无法认为 “ /bin/bsah ”是一个整体 sed:-e 表达式 #1,字符 8:“s”的未知选项 [root@room13pc37 shell_test]# sed -n 's/\/bin\/bash/\/bin\/sh\/p' tset_sed.s.txt #可以通过反斜杆来 " /bin/bash "的 / 转义 #同时我们可以使用其他字符来代替 " s /// "的次操作符号。(数字键(0~9)上的符号都可以使用, 要求操作的符号一致即可) [root@room13pc37 shell_test]# sed -n 's$/bin/bash$/bin/sh$p' tset_sed.s.txt root:x:0:0:root:/root:/bin/sh #增加注释、取消注释 [root@room13pc37 shell_test]# sed '4,7s/^/#/' test.txt //将第4~7行注释掉(行首加#号) [root@room13pc37 shell_test]# sed 's/^#an/an/' test.txt //解除以#an开头的行的注释(去除行首的#号)
-
例子 替换文件的内容:
#首先创建一个素材文件
[root@room13pc37 shell_test]# cat nssw.txt
hello the world
ni hao ma beijing
#删除文件中每行的第二个、最后一个字符
#分两次替换操作,第一次替换掉第2个字符,第二次替换掉最后一个字符:
#方法1
[root@room13pc37 shell_test]# sed 's/.//2;s/.$//' nssw.txt # 用 . 来匹配任意一个字符。实现删除 多个个动作指令用 ; 隔开
hllo the worl
n hao ma beijin
#方法2
[root@room13pc37 shell_test]# sed -r 's/^(.)(.)(.*)(.)$/\1\3\4/;s/(.*)(.)$/\1/' nssw.txt
hllo the worl
n hao ma beijin
#将文件中每行的第一个、倒数第1个字符互换
#每行文本拆分为“第1个字符”、“中间的所有字符”、“倒数第1个字符”三个部分,然后通过替换操作重排顺序为“3-2-1
[root@room13pc37 shell_test]# sed -r 's/^(.)(.*)(.)$/\3\2\1' nssw.txt #互换位置
dello the worlh
gi hao ma beijinn
[root@room13pc37 shell_test]# sed -r 's/^(.)(.*)(.)$/\3\1/' nssw.txt #删除中间部分内容。
dh
gn
#1.使用拓展的正则,需要加 -r选项。
#2.() 是保留的作用。
#3.^(.)==保留第一行开头的字符;同理(.)$ ==保留最后一行的字符。
#4.保留的字符可以使用 \1、\2、\3 分别来代替 前面的()的内容。可以通过重排实现字符之间位置互换,类是与粘贴、剪切。
#5.有多个()就表示有多少部分,对于多少个\num。 \num的数量不能大于()的部分
-----------------------------------------------------------------------------------
- 例子把该文件的中的数字,行首的空格删除掉
[root@room13pc37 shell_test]# cat nssw.txt
Hello the wo8rod
ni h4ao m6a beijing #前面是有空格的
#方法1
[root@room13pc37 shell_test]# sed -r 's/[0-9]//g;s/^( *)(.*)/\2/' nssw.txt #使用() 保留的方法, 注意:( *)括号里面有空格
Hello the worod
ni hao ma beijing
#方法2
[root@room13pc37 shell_test]# sed -r 's/^ +//;s/[0-9]//g' nssw.txt # "^ +" 之间有一个空格
Hello the worod
ni hao ma beijing
#若要保存修改,可以加上 -i 选项
- 例子找出该文件的中的大写字母,并且给大写字母加行括号
[root@room13pc37 shell_test]# cat nssw.txt
Hello The worod
ni hao ma Beijing
[root@room13pc37 shell_test]# sed -r 's/([A-Z])/(\1)/g' nssw.txt #使用() 粘贴复制,给\1加上()
(H)ello (T)he worod
ni hao ma (B)eijing
#[A-Z] 在这里是每一个行逐个查找
- 应用1编写anonftp.sh脚本,用来装配匿名FTP服务
#!/bin/bash
yum -y install vsftpd
cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.old #把源有的文件做一个备份,
sed -i 's/^#anon_u/anon_u /' /etc/vsftpd/vsftpd.conf
chmod o+w /var/ftp/pub
systemctl restart vsftpd
systemctl enable vsftpd
sed 文本块处理
- 文本块处理动作:
操作符 | 用途 | 指令集合 |
---|---|---|
i | 行前插入文本 | 2iYY (在第2行之前添加文本行“YY”), 4,7iYY (在第4-7 行的每一行前添加文本) |
a | 行后插入文本 | 2aYY (在第2行之后追加文本“YY”)、 /^XX/aYY (在以XX开头的行后添加文本 ) |
c | 替换当前行 | 2cYY (将第2行的内容修改为 “YY” ) |
- 应用
#单行文本处理
[root@server0 shell]# cat abc #素材文件
#a
[root@server0 shell]# sed 'a 666' abc #在文本行的每一行后面添加
[root@server0 shell]# sed '1a 666' abc #在文本行的第一行后面添加
#c
[root@server0 shell]# sed '1c 666' abc #在文本行的每一行替换
[root@server0 shell]# sed 'c 666' abc #在文本行的第一行替换
#i
[root@server0 shell]# sed 'i 666' abc #在文本行的每一行前面添加
[root@server0 shell]# sed '1i 666' abc #在文本行的第一行前面添加
#多行文本处理
- 导入到处操作
- 基本动作
- -r 动作结合 -i 选项才会存入,否则只是输出
- -w 动作以覆盖的方式另存为新文件
- 基本动作
操作符 | 用途 | 指令集合 |
---|---|---|
r | 读取文件 | 3rb.txt (在第3行下方插入文本b.txt)、4.7rb.txt(在第4到7行后插入文件b.txt) |
w | 保存到文件 | 3wc.txt (在第3行另存为文本c.txt)、4.7wc.txt(在第4到7行另存为文件c.txt) |
[root@server0 shell]# sed 'r 123' abc
[root@server0 shell]# touch 123
[root@server0 shell]# sed 'w 123' abc
abcd
666
xyz
[root@server0 shell]# cat 123
abcd
666
xyz
[root@server0 shell]# sed 'w 1234' abc #若写入覆盖的文件的文件不存在,则会自动创建该文件
abcd
666
xyz
[root@server0 shell]# ls
1234 abc 123
sed综合脚本应用
1. 本案例要求编写脚本getupwd.sh,实现以下需求:
找到使用bash作登录Shell的本地用户
列出这些用户的shadow密码记录
按每行“用户名 --> 密码记录”保存到getupwd.log
[root@server0 shell]# cat getupwd.sh
#!/bin/bash
A=$(sed -n '/bash$/s/:.*//p' /etc/passwd)
for i in A
do
pass1=$(grep $i /etc/shadow)
pass2=${pass1#*:}
pass3=${pass2%%:*}
echo "$i ----> $pass3"
done
[root@server0 shell]# bash getupwd.sh
A ----> $6$UiGI4Tc2$htsXYn5cJnOqv3P1VLcUSgfjDu2pL5yiJBuua6foZAHdwqeuLHfYUfS/vBn27Wjvoel8EJgtdsMjyquqvKAmf1
- 总结:
总结知识点:
#sed [选项] ‘条件指令’ 文件
选项:
-n 屏蔽默认输出
-r 支持扩展正则
-i 修改源文件
条件:
行号 4 4,5 4~2 4,+10
/正则/
指令:
p 打印
d 删除
s 替换s/旧/新/g
a 追加
i 插入
c 替换行