sed

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的模式空间的了解

微信图片_20200112180345.png

扩展的: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


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。