sed

1、概述

.

  • 核心功能:取行、过滤、替换修改文件内容
  • 难点:后向引用(截取)
  • sed stream editor(流式编辑器)

2、命令格式

  • 命令格式1:前置命令 | sed [选项] '[指令]' 文件名

  • 命令格式2:sed [选项] '[指令]' 文件名

参数 含义
-n 屏蔽默认输出,默认sed会将所有的输出结果输出到屏幕中,-n只把sed处理的行输出到屏幕
如果不使用-n参数,那么输出的内容会输出两遍,也就是说-n屏蔽的是sed -p的默认输出
-i 直接修改文件内容,如果不加-i选项,并不会真正改变文件的内容
-r 使用扩展正则,若与其他选项一起使用,此选项应该在首位
-i.bak 修改文件内容之前先进行备份,然后再修改内容(一般用于替换一个文件),这个参数要放在所有参数的最后面

3、执行流程

sed 的工作流程

  • 读取:sed从输入流(文件、管道、stdin)中读取一行内容并保存到临时文件缓冲区中(又称模式空间:pattern space)

  • 执行:默认情况下,所有的sed命令都在模式空间中顺序地执行,除非制定了行的地址,否则sed命令将会在所有命令行上依次执行

  • 显示:发送修改后的内容到输出流,在发送数据后,模式空间(pattern space)将会被清除

在所有的文件内容都被处理完成之前,上述过程将会重复执行,直至所有的内容被处理完成

在默认情况下,所有的sed命令都是在pattern space中完成的,因此输入的文件不会有任何变化,除非是用重定向存储输出

4、sed查找

一种是类似于grep的模糊查找(正则查询)

​ 类似于grep命令的过滤,比grep强在可以指定行号

一种是精确查找,行号

(1)、取出文件的第3行

-n:取消默认输出,sed在处理文件的时候会默认的输出每一行的内容

p:表示输出,一般和-n搭配使用

[root@Ansible-server opt]# sed -n '3p' a.txt 
goooood

(2)、取出2到5行

[root@Ansible-server opt]# sed -n '2,5p' /etc/passwd 
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

(3)、取出2行和5行

[root@Ansible-server opt]# sed -n '2p;5p' /etc/passwd 
bin:x:1:1:bin:/bin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

(4)、过滤出包含root的行

⚠️sed支持过滤某一个内容

/内容/p,打印出过滤的内容

sed支持正则,默认是支持基础正则

-r参数可以让其支持扩展正则

[root@Ansible-server opt]# sed -n '/root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
stap-server:x:155:155:Systemtap Compile Server:/opt/rh/gcc-toolset-11/root/var/lib/stap-server:/sbin/nologin
[root@Ansible-server opt]# sed -n '/^root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@Ansible-server opt]# sed -r -n '/^(root|bin)/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

(5)、模拟过滤日志

[root@Ansible-server log]# cat sed.txt 
101,xiaoxu,ccc
102,xiaoli,bbb
103,xiaowang,ddd
104.xiaozhao,qqq
110.xxx,vvv
[root@Ansible-server log]# sed -n '/101/ , /104/p' sed.txt 
101,xiaoxu,ccc
102,xiaoli,bbb
103,xiaowang,ddd
104.xiaozhao,qqq

(6)、从某一行开始取几行

[root@moudle01 20:05:08  ~]# head -5 user 
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
[root@moudle01 20:06:26  ~]# sed -n "3,+1p" user 
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@moudle01 20:06:38  ~]# sed -n "3,+2p" user 
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

(7)、~

从某一行开始,按照某一步长去进行读取

[root@moudle01 20:10:03  ~]# cat abc 
1
2
3
4
5
6
7
8
9
0

[[root@moudle01 20:09:51  ~]# sed -n "1~2p" abc 
1
3
5
7
9

(8)、查找某一内容在第几行

# 输出除了第一行的内容
[root@moudle01 20:20:12  ~]# sed -n '1!p' user
# 输出最后一行
[root@moudle01 20:20:12  ~]# sed -n '$p' user 
abc:x:1021:1021::/home/abc:/bin/bash
# 输出某一内容在第几行
[root@moudle01 20:16:22  ~]# sed -rn "/^apache/=" user 
30

(6)、查找功能小结

  • 核心掌握:
    • 根据行号查找,模糊查找//,模糊表示范围(日志)
    • 注意这里提到的行号,//方式到表示条件(找谁),除了给p(查找)用,还可以给修改,增加,删除使用
  • 过滤时与grep类似支持正则表达式,sed -r支持扩展正则
  • sed可以指定行号,sed表示过滤范围

5、sed修改(替换)

sed命令的替换格式说明

sed 's#找谁#提供换成什么#g' sed.txt

sed 's###g' sed.txt

推荐使用: ### @@@ ///

当查找替换的内容是# @ / 时就不要使用对应的符号作为分隔符了

s substitute 替换

g global 全局替换,这一行中把所有匹配到的内容都进行替换,如果不加g,则只替换每一行的第一个匹配到的内容

-i参数:直接修改文件内容,如果不加-i选项,并不会真正改变文件的内容。动作指令d、s和选项-i是在搭配一起使用的

修改文件内容之前先进行备份,然后再修改内容(一般用于替换一个文件) -i.bak

[root@Ansible-server log]# sed 's#[0-9]#ccc#g' sed.txt 
ccccccccc,xiaoxu,ccc
ccccccccc,xiaoli,bbb
ccccccccc,xiaowang,ddd
ccccccccc.xiaozhao,qqq
ccccccccc.xxx,vvv
[root@Ansible-server log]# sed 's#[0-9]#ccc#' sed.txt 
ccc01,xiaoxu,ccc
ccc02,xiaoli,bbb
ccc03,xiaowang,ddd
ccc04.xiaozhao,qqq
ccc10.xxx,vvv
[root@Ansible-server log]# sed -i.bak 's#xiaoxu#lili#g' sed.txt 
[root@Ansible-server log]# ls sed.txt
sed.txt
[root@Ansible-server log]# ll  sed.txt*
-rw-r--r--. 1 root root 74 May  5 19:59 sed.txt
-rw-r--r--. 1 root root 76 May  5 19:16 sed.txt.bak
# 把所有行的第二个符合条件数据替换
[root@moudle01 20:36:47  ~]# sed 's/2017/xxxx/2' sucai.txt 
2017 2011 2035
2017 xxxx 4534
2017 xxxx 2017
# 把所有行的第三个符合条件数据替换
[root@moudle01 20:37:43  ~]# sed 's/2017/xxxx/3' sucai.txt 
2017 2011 2035
2017 2017 4534
2017 2017 xxxx
# 只替换第二行的 第二个数据
[root@moudle01 20:37:48  ~]# sed '2s/2017/xxxx/2' sucai.txt 
2017 2011 2035
2017 xxxx 4534
2017 2017 2017
# 在行号位置加正则
[root@moudle01 20:40:38  ~]# sed '/4534$/s/2017/xxxx/2' sucai.txt 
2017 2011 2035
2017 xxxx 4534
2017 2017 2017

面试题

有一个文件,执行如下命令,会发生什么

sed  's9\98\9\99\978\99'  filename

\:是转义字符

是以9作为分隔符

s9 \98\9\9 9 \987\9 9

将文件中的9899修改为9879

🔑s后面的第一个字符就是分隔符

  • 小结
    • 核心掌握sed命令替换的格式
    • 核心掌握-i用法

6、sed替换进阶

(1)、后向引用格式

应用说明

后向引用或反向引用:适用于sed命令处理/提取某一行中的部分内容,sed命令配合正则实现取列(类似于awk命令)

是sed命令中用于处理列的方式

使用格式

使用替换形式:s###g

前2个井号之间通过正则与(),对数据进行分组,每一个()是一个组

后面两个井号之间通过\数字,去调用前面分组的内容

整体式后面调用前面分组的内容,称之为反向引用/后向引用

应用场景:某一行中对部分数据进行加工与处理,提取某一部分数据

[root@Ansible-server log]# echo 12345678 | sed -r 's#(1)(.*)(8)#\1<\2>\3#g' 
1<234567>8

(2)、案例01

交换/etc/passwd下第一列和第二列的内容

[root@Ansible-server opt]# sed -r 's#(^.*)(:.*:)(.*$)#\3\2\1#g' passwd 
/bin/bash:/root:root:x:0:0:root

(3)、案例02

提取IP

[root@Ansible-server opt]# ip address show ens160 | sed -n '4p' | sed -r 's#(^.* )(.*)(/.*$)#\2#g'
192.168.121.141

(4)、案例03

root@moudle01[09:32:33]:/script
$ cat abc.txt 
100 laownag
89 xxx
666 w
root@moudle01[09:32:24]:/script
$ sed -r 's/([0-9]+)(\s+)(\w+)/\3\2\1/' abc.txt 
laownag 100
xxx 89
wu 666

7、sed删除

  • d:sed命令删除是按照为单位进行
  • 如果仅仅删除某一行的一个字符,使用替换
[root@Ansible-server opt]# sed  '1,3d' /var/log/sed.txt
104.xiaozhao,qqq
110.xxx,vvv
  • 案例

  • 排除文件中的空行和带注释的行

    [root@Ansible-server opt]# sed -r '/^$|#/d' /etc/ssh/sshd_config
    [root@Ansible-server opt]# egrep -v '^$|#' /etc/ssh/sshd_config
    [root@Ansible-server opt]# awk '!/^$|#/' /etc/ssh/sshd_config
    
# 除了bin开头的行,其他行全删除
[root@moudle01 20:26:29  ~]# sed '/^bin/!d' user 
bin:x:1:1:bin:/bin:/sbin/nologin
# 删除文件最后一行
[root@moudle01 20:29:11  ~]# sed '$d' user

8、sed增加

  • cai
    • a:append,在指定行下面追加内容
    • i:insert,在指定行上面加上内容
    • c:replace,清空当前行,后续的内容作为当前行的内容
[root@Ansible-server opt]# cat sed.txt 
101,lili,ccc
102,xiaoli,bbb
103,xiaowang,ddd
104.xiaozhao,qqq
110.xxx,vvv
[root@Ansible-server opt]# sed '3a hahaha' sed.txt 
101,lili,ccc
102,xiaoli,bbb
103,xiaowang,ddd
hahaha
104.xiaozhao,qqq
110.xxx,vvv
[root@Ansible-server opt]# sed '3i hahaha' sed.txt 
101,lili,ccc
102,xiaoli,bbb
hahaha
103,xiaowang,ddd
104.xiaozhao,qqq
110.xxx,vvv
[root@Ansible-server opt]# sed '3c hahaha' sed.txt 
101,lili,ccc
102,xiaoli,bbb
hahaha
104.xiaozhao,qqq
110.xxx,vvv
posted @ 2024-07-16 11:30  Linux小菜鸟  阅读(4)  评论(0编辑  收藏  举报