sed遵循简单的工作流:
读取(从输入中读取某一行)
执行(在某一行上执行sed命令)
显示(把结果显示在输出中)
默认是显示修改后内容,不会修改原文件,除非使用-i 参数。
常用参数及命令
sed [-nefri] 'command' test.txt (尽量按照标准格式使用单引号)
sed | 处理文本文件,并输出到标准输出(控制台) | command | |||
---|---|---|---|---|---|
-e | 可以指定多个命令 | a | 新增 | ||
-f | 指定命令文件 | c | 替换 | ||
-n | 取消默认控制台输出,与p一起使用可打印指定内容 | d | 删除 | ||
-i | 输出到原文件,静默执行(修改原文件的意思) | i | 插入 | ||
-r | 支持扩展正则符号 | p | 打印,要和-n参数一起使用 | ||
s | 替换(匹配局部替换) | ||||
l | 列出非打印的字符 | ||||
r | 从文件中间读取 | ||||
g | 全局替换的时候用 | ||||
w | 将行写入文件中 |
以下为扩展
h 清除保持空间的内容后,把模式空间里的内容复制到保持空间
H 把模式空间里的内容追加到保持空间
g 清除模式空间的内容后, 取出保持空间的内容,并复制到模式空间
G 取出保持空间的内容,追加在模式空间原有内容的后面
x 交换模式空间与保持空间的内容
注意:匹配模式 是可选的用于在文件中每一行进行匹配到模式,模式可以是正则,也可以是文件的行号
内部的命令也是可选的,没想到吧,但是两个单引号是必须的
-r:支持扩展正则符号
与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式是
括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。
使用基本元字符集 ^, $, ., *, [], [^], < >,(),{}
使用扩展元字符集 ?, +, { }, |, ( )使用扩展元字符的方式:sed -r
在实际使用的时候,都会加上 -r 参数,即使没有用的扩展正则也不会有任何影响。
p:打印
打印输出到屏幕上
[root@localhost shell_learning_new]# sed -r '' mypasswd
1:root:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
...
[root@localhost shell_learning_new]# sed -r 'p' mypasswd
1:root:x:0:0:root:/root:/bin/bash
1:root:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
2:bin:x:1:1:bin:/bin:/sbin/nologin
...
-n:取消默认控制台输出,与p一起使用可打印指定内容
屏蔽默认输出使用 -n 选项
[root@localhost shell_learning_new]# sed -rn '' mypasswd ##屏蔽全部默认输出后就看不到了
[root@localhost shell_learning_new]# sed -rn 'p' mypasswd
1:root:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
- 下面插入一个匹配文件内容的方法
[root@localhost shell_learning_new]# sed -rn '/root/p' mypasswd #和vim或者awk有点像的 也是'/xxx/'
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
替换 c
sed '2c testContent' test.txt
将第 2 行内容整行替换(注意这里没有0c的匹配;1c就是第一行了)
sed '1,3c testContent' test.txt
将第 1~3 行内容替换成一行指定内容
局部替换s
替换的时候会自动查找匹配项,把匹配项执行后面的命令,默认是 p 打印(不加 -n 的情况下)
[root@localhost shell_learning_new]# sed -r 's/root/XXXX/' mypasswd
1:XXXX:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
。。。。
10:operator:x:11:0:operator:/XXXX:/sbin/nologin
[root@localhost shell_learning_new]# sed -rn 's/root/XXXX/p' mypasswd 每行匹配到的第一个替换
1:XXXX:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/XXXX:/sbin/nologin
.............................................
加g表示全局替换
[root@localhost shell_learning_new]# sed -rn 's/root/XXXX/gp' mypasswd 加g表示每一列都替换
1:XXXX:x:0:0:XXXX:/XXXX:/bin/bash
10:operator:x:11:0:operator:/XXXX:/sbin/nologin
.............................................
加i表示不区分大小写
[root@localhost shell_learning_new]# echo "root ROOT" |sed 's/root/tiger00/gi'
tiger00 tiger00
[root@localhost shell_learning_new]# echo "root ROOT" |sed 's/root/tiger00/g'
tiger00 ROOT
在模式匹配的使用中使用其他界定符号时,需要对其进行转译。而在使用s的时候不需要进行转译。
新增 a (加在下一行)
sed '2a testContent' test.txt
在第 2 行后面新增一行内容
sed '1,3a testContent' test.txt
在原文的第 1~3 行后面各新增一行内容
删除 d
sed '2d' test.txt #删除第 2 行
sed '1,3d' test.txt #删除第1~3行
sed -r '/root/ d' mypasswd #匹配含有root的行删除
sed -r '/root/,5 d' mypasswd #匹配含有root的行开始删除到文章的第五行
sed -r '/root/,+2 d' mypasswd #匹配含有root的行开始删除,并删除接下来的2行,一共删除3行
sed -r '/root/ !d' mypasswd #匹配含有root的行,除了含有root的行其他的都删除
sed -r '1~3 d' mypasswd #匹配行数为被三整除的并且余1的行,删除它
插入 i(和a是反的)
sed '2i testContent' test.txt
在第 2 行前面插入一行内容
sed '1,3i testContent' test.txt
在原文的第 1~3 行前面各插入一行内容
r读文件到本文件下
在 mypasswd 文件的第二行下面,插入 从 /etc/hosts 文件中读取到的内容
sed -r '2r /etc/hosts' mypasswd
在 mypasswd 文件中含有字符 2 下面,插入 从 /etc/hosts 文件中读取到的内容
sed -r '/2/r /etc/hosts' mypasswd
w写文件
把 mypasswd 文件中含有 字符 root 的行写入到文件 newfile, newfile 文件不存在则创建,存在则覆盖
sed -r '/root/w newfile' mypasswd
把 mypasswd 文件中的第 3 行到最后的内容写入到文件 /new1.txt 中
sed -r '3,$w /new1.txt' mypasswd #是覆盖的
c修改命令
[root@localhost ~]# sed -r '2c\1111111111' /root/shell_learning_new/mypasswd
[root@localhost ~]# sed -r '2c 1111111111' /root/shell_learning_new/mypasswd #把第二行修改成1111111111
...................................
[root@localhost ~]# sed -r '2c\111111111111\ 2222222222222\
3333333333333' /root/shell_learning_new/mypasswd
1:root:x:0:0:root:/root:/bin/bash
111111111111
2222222222222
3333333333333
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
n匹配到的行不执行,下一行执行
[root@localhost ~]# sed -r '/root/{n;d}' /root/shell_learning_new/mypasswd #匹配第一行有root的,但是在第二行执行了
1:root:x:0:0:root:/root:/bin/bash
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
sed的模式空间的了解
扩展的:h H g G x
以下为扩展
h 清除保持空间的内容后,把模式空间里的内容复制到保持空间
H 把模式空间里的内容追加到保持空间
g 清除模式空间的内容后, 取出保持空间的内容,并复制到模式空间
G 取出保持空间的内容,追加在模式空间原有内容的后面
x 交换模式空间与保持空间的内容
- 注意:模式空间的内容只有当前处理的那一行的内容;处理完一行之后就会输出
sed -r '1h;$G' /root/shell_learning_new/mypasswd
#匹配第一行后清空保持空间的内容后,把模式空间里的内容复制到保持空间;
#匹配到最后一行之后取出保持空间的内容,追加在模式空间原有内容的后面。
[root@localhost ~]# sed -r '4h;5x;6G' /root/shell_learning_new/mypasswd
1:root:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
6:sync:x:5:0:sync:/sbin:/bin/sync
5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8:halt:x:7:0:halt:/sbin:/sbin/halt
9:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin
-e:多重编辑 (也可以用;
)
[root@kube-master sed]# sed -e '1,3 d' -e 's/root/shark/' mypasswd
#一到三行删除,匹配root第一个匹配行替换
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8:halt:x:7:0:halt:/sbin:/sbin/halt
9:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/shark:/sbin/nologin
练习
删除配置文件中 # 号注释的行
sed -ri '/^#/d' file.conf
删除开头的一个或者多个 空格或者 Tab 键的带#的行
sed -ri '/^[ \t]*#/d' file.conf
YUM 源修改
sudo sed -ri s/^#baseurl/baseurl/g /etc/yum.repos.d/CentOS-Base.repo
sudo sed -ri s/^mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOSBase.repo
空格和table键 '/^#/d' [ \t] * 空格和table
删除配置文件中//号注释行
sed -ri '\Y^[ \t]*//Yd' file.conf #要转换分隔的匹配的符号,用\转译Y
删除无内容空行
- 开头和结尾之间什么都没有的行
- 开头和结尾之间有多个空格的行
- 开头和结尾之间有多个 Tab 键的行
sed -ri '/^[ \t]*$/d' file.conf
删除注释行及空行:
以下 3 中效果一样,挑一个自己喜欢的
sed -ri '/^[ \t]*#/d; /^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
sed -ri '/^[ \t]*#|^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
sed -ri '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf
修改文件:
sed -ri '$a\chroot_local_user=YES' /etc/vsftpd/vsftpd.conf
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
sed -ri '/GSSAPIAuthentication/cGSSAPIAuthentication no' /etc/ssh/sshd_config
给文件行添加注释:
sed -r '2,6s/^/#/' a.txt
使用小括号进行分组,可以有多个分组, 后面可以使用 \1 获取到第一个分组的内容
sed -r '2,6s/(.*)/#\1/' a.txt
sed -r '2,6s/.*/#&/' a.txt &匹配前面查找的内容;注释所有的项目
sed -r '3,$ s/^#*/#/' a.txt 将行首零个或多个#换成一个#
sed -r '30,50s/^[ \t]*#*/#/' /etc/nginx.conf
sed -r '2,8s/^[ \t#]*/#/' /etc/nginx.conf
sed中使用外部变量
var1=11111
# 无效
sed -r '3a$var1' /etc/hosts
# 正确
sed -r "3a$var1" /etc/hosts
# 有效
sed -r 3a$var1 /etc/hosts
# 报错
sed -r "$a$var1" /etc/hosts
# 有效,但是中间不能有空格
sed -r '$a'"$var1" /etc/hosts
# 有效, 将第一个 $ 进行转义
sed -r "\$a $var1" /etc/hosts
sed -rn 's/(sha256:\w{12}).*? (sha256:\w{12}).*/\1 \2 /gp' sed-txt
#要匹配sha256:+12个字母或数字;这里的?为非贪婪,具体详解在shell编程(4)正则中
sed -rn '=;s/(sha256:\w{12})\w.*/\1/gp' sed-txt # '=' 为输出行号
匹配的文档内容
sha256:65dc03343afa sha256:196d12cf6ab19273823e700516e98eb1910b03b17840f9d5509f03858484d321
[centos7-ssh-iproute:latest] sha256:10a2411f52e96abda5deb6301812c5eeba27d543e3ec3713c10b1543eea8f4b6 sha256:b4f8b82a5471b405d1f7c3f9f2b79cfbb5a0dc99e62ec36f7e254326abaf3941
[] sha256:b4f8b82a5471b405d1f7c3f9f2b79cfbb5a0dc99e62ec36f7e254326abaf3941 sha256:7b036082ee3589f8c1ae98d0f77d9aa834860a93dc824c658ab8fc1d4d62f775
[] sha256:7b036082ee3589f8c1ae98d0f77d9aa834860a93dc824c658ab8fc1d4d62f775 sha256:f8f2c35ea601ab92b6bf951b88cda3c0d2d53b50a7148b7b3dedd30265251cbc
[] sha256:f8f2c35ea601ab92b6bf951b88cda3c0d2d53b50a7148b7b3dedd30265251cbc