三剑客与正则系列 - sed 命令
1.1 概述
- 核心功能:取行,过滤,替换修改文件内容。
- 难点:后向引用(截取)。
- sed stream editor 流编辑器。
1.2 格式
命令 | 选项 | 详细格式 | 参数 |
---|---|---|---|
sed | 选项 | ' 条件动作' | 文件 |
' 找谁干啥' |
1 找谁:条件,匹配哪一行,哪些行。
2 干啥:动作,增删改查。
3 #显示文件的第 3 行
4 sed -n '3p' /etc/passwd
选项 | 说明 |
---|---|
-n | 取消默认输出 |
-r | sed 支持扩展正则 |
-i | 修改文件内容,这个选项放在最后。 |
-i.bak | 先进行备份,然后修改文件内容,这个选项放在最后。 |
1.3 sed 增删改查之查找
一种是类似于 grep 模糊查找。一种是精确查找,行号。
- 类似于 grep 命令的过滤,比 grep 强在于可以指定行号。
- 类似于 grep 命令的功能,模糊查询(通过正则)。
1)案例 01:取出文件的第 3 行
-n 表示取消默认输出,sed 处理文件的时候会默认的输出每一行内容。
sed -n '3p' /etc/passwd
2)案例 02:取出 /etc/passwd 的第 2 行到第 5 行
sed -n '2,5p' /etc/passwd
3)案例 03:过滤出 /etc/passwd 中包含 root 的行
grep 'root' /etc/passwd
[root@oldboy-king-v3 oldboy]# sed -n '/root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin[root@oldboy-king-v3 oldboy]# sed -n '/^root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
⚠️注意sed 进行过滤的时候需要使用 // 并且里面支持基础正则如果需要使用扩展正则需要使用 sed -r 选项
4)案例 04:获取范围内的日志
cat >/oldboy/sed.txt<<EOF
101,oldboy,CEO
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
EOF
[root@oldboy83-prod oldboy]# #sed -n '/从哪里来/,/到哪里去/p' sed.txt
[root@oldboy83-prod oldboy]# sed -n '/bigbao/,/lidao/p' sed.txt
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
[root@oldboy-85-vip-king-v2 oldboy]# sed -n '/102/,/105/p' sed.txt
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy-85-vip-king-v2 oldboy]# #sed -n '/10:00:00/,/11:00:00/p' sed.txt
- 试着取出 access.log 过滤出 11:05 分到 11:06 分的日志
#wc -l 统计行数
[root@oldboy83-prod oldboy]# sed -n '/11:05:00/,/11:06:00/p' access.log |wc -l
3366
[root@oldboy83-prod oldboy]# sed -n '/11:05/,/11:06/p' access.log |wc -l
3383
[root@oldboy83-prod oldboy]# sed -n '/2015:11:05:00/,/2015:11:06:00/p' access.log |wc -l
3366
[root@oldboy83-prod oldboy]# sed -n '/Nov\/2015:11:05:00/,/Nov\/2015:11:06:00/p' access.log |wc -l
3366
[root@oldboy83-prod oldboy]#
5)sed 命令过滤 / 查找功能小结
- 核心掌握:
- 根据行号查找,模糊查找 //,模糊表示范围(日志)
- 注意这里提到的指定行号,// 方式都表示条件(找谁),除了给 p(查找)用,还可以给改,增加,删除。
- 过滤的时候与 grep 类似支持正则表达式,sed -r 支持扩展正则。
6)只显示第 2 行和第 5 行
sed -n '2p;5p' /etc/passwd
[root@oldboy83-prod oldboy]# cat -n sed.txt1 101,oldboy,CEO2 102,bigbao,CTO3 103,李导996,COO4 104,yy,CFO5 105,feixue,CIO6 110,lidao,COCO
[root@oldboy83-prod oldboy]# sed -n '2p ; 5p' sed.txt
102,bigbao,CTO
105,feixue,CIO[root@oldboy83-prod oldboy]# pwd;whoami;hostname
/oldboy
root
oldboy83-prod
7)表示有规律的查找 - 了解
seq 10:生成从 1 到 10 的连续数字(1、2、3...10)
1~2p:sed 的动作部分,其中:1 表示起始行(从第 1 行开始),~2 表示步长为 2(每隔 2 行取一次)
p 表示打印动作[root@oldboy-king-v3 oldboy]# seq 10 |sed -n '1~2p'
1
3
5
7
9
[root@oldboy-king-v3 oldboy]# seq 10 |sed -n '2~2p'
2
4
6
8
10
1.4 sed 增删查改之修改
- sed 的修改叫做替换。
sed 命令的替换格式说明:
sed 's#找谁#替换成什么#g' sed.txt
sed 's###g' sed.txt
推荐使用:###,@@@,///
-
s substitute 替换 sub
-
g global 全局替换,这一行中把所有匹配到的内容都进行替换,否则只替换每一行第 1 个匹配的内容
1)案例 05:把 sed.txt 文件中 lidao 替换为 oldboy
[root@oldboy83-prod oldboy]# cat sed.txt
101,oldboy,CEO
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO[root@oldboy83-prod oldboy]# sed 's#lidao#oldboy#g' sed.txt
101,oldboy,CEO
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO
- 修改文件内容之前进行备份,然后修改文件内容
sed -i.bak 's#bigbao#oldbao#g' sed.txt
-i后面可以加上一些额外的内容 -i.bak表示先对sed.txt进行备份 sed.txt.bak
然后对文件内容进行替换
一般用于替换某一个文件,如果是多个文件就打包压缩进行备份即可。
- 小结
- 核心掌握 sed 命令替换的格式。
- 核心掌握 - i 用法。
1.5 增删改查之替换 - 进阶
1)后向引用格式
应用说明:后向引用或反向引用:适用于 sed 命令处理 / 提取一行中的某一部分。sed 命令配合正则实现取列。(类似于 awk 取列)
sed 命令中用于处理列的方式。
使用格式:使用替换的形式 s###g
前 2 个井号之间通过正则与 (),对数据进行分组。
后面 2 个井号之间通过 \ 数字,去调用前面分组的内容。
整体是后面调用前面分组的内容,称之为反向引用 / 后向引用。
应用场景:某一行中对部分数据进行加工与处理,提取某一部分数据。
- 例子
输出 12345678,通过 sed 加工变成 1<234567>8
echo 12345678 |sed -r 's#(1)(.*)(8)#\1<\2>\3#g'
1<234567>8
2)案例 01:调换 /etc/passwd 第 1 列和最后一列内容
root:x:0:0:root:/root:/bin/bash
三部分,root :x :0:0:root:/root : /bin/bashsed -r 's#^(.*)(:x.*:)(.*$)#\3\2\1#g' passwd分组逻辑(通过 () 划分三个组):
^(.*):第 1 组,匹配行开头到第一个 :x 前的内容(通常是用户名,如 root)。
(:x.*:):第 2 组,匹配从 :x 开始到最后一个冒号前的内容(包含密码占位符 x、UID、GID 等中间字段,如 :x:0:0:root:/root:)。
(.*$):第 3 组,匹配最后一个冒号到行尾的内容(通常是登录 Shell,如 /bin/bash)。
替换规则:\3\2\1 表示用「第 3 组 + 第 2 组 + 第 1 组」的顺序重组内容,即最后一列放到最前面,第一列放到最后面,中间字段保持不变。
原行:root:x:0:0:root:/root:/bin/bash
替换后:/bin/bash :x :0:0:root:/root : root^([a-zA-Z0-9_-]+)(:.*:)(/.*)$
分组逻辑(更精确的字段约束):
^([a-zA-Z0-9_-]+):第 1 组,严格匹配由字母、数字、下划线、短横线组成的字符串(符合 Linux 用户名规范,如 root、oldboy)。
(:.*:):第 2 组,匹配两个冒号之间的所有内容(中间字段,同前)。
(/.*)$:第 3 组,严格匹配以 / 开头的路径(符合登录 Shell 或家目录的格式,如 /bin/bash)。
3)案例 02:取出网卡 ip 地址
ip a s eth0 取出第 3 行里面的 ip 地址
方法 01
[root@oldboy-king-v3 oldboy]# ip a s eth0 | sed -n '3p' | sed -r 's#^.*et ([0-9.]+)/.*$#\1#g'
s# ^.*et ([0-9.]+)/.*$ # \1 #g
10.0.0.200方法 02 进阶
sed -n '3p'
+
sed -r 's#^.*et ([0-9.]+)/.*$#\1#g'
= sed -nr '3 s#^.*et ([0-9.]+)/.*$#\1#g p'方法 03 awk
[root@oldboy-king-v3 oldboy]# ip a s eth0 | sed -n '3p' |awk '{print $2}' | sed's#/24##g'
10.0.0.200方法 04 awk
[root@oldboy-king-v3 oldboy]# ip a s eth0 | sed -n '3p' |awk -F "[ /]+" '{print $3}'
10.0.0.200方法 05-06 awk
ip a s eth0 | sed -n '3p' |awk -F "[/]+" '{print $3}'[root@oldboy-king-v3 oldboy]# ip a s eth0 | awk -F " [ /]+" 'NR==3{print $3}'
10.0.0.200方法 07
hostname -I
4)案例 03:取出 stat /etc/hosts 中的 0644 或 644
[root@oldboy-king-v3 oldboy]# stat /etc/hosts |sed -n '4p' | sed -r 's#^.*\(([0-9]+)/.*$#\1#g'
0644
1.6 增删改查之删除
- d delete 删除 sed 命令删除功能按照行为单位进行。
- 如果仅仅删除某一行的一些字符推荐使用's#[a-z]##g'
sed '3d' sed.txt
101,oldboy,CEO
102,oldbao,CTO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO
- 排除 / 删除文件中的空行和带注释的行
egrep -v '^$|#' /etc/ssh/sshd_config
sed -r '/^$|#/d' /etc/ssh/sshd_config
awk '! /^$|#/' /etc/ssh/sshd_config
sed -nr '/^$|#/!p' /etc/ssh/sshd_config
1.7 增删改查之增加
- cai
- a append 在指定行后面追加内容
- i insert 在指定行上面插入一行
- c replace 替换指定行的内容
[root@oldboy-king-v3 oldboy]# cat sed.txt
101,oldboy,CEO
102,oldbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO[root@oldboy-king-v3 oldboy]# sed '3a 999,lidao007,UFO' sed.txt
101,oldboy,CEO
102,oldbao,CTO
103,李导996,COO
999,lidao007,UFO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO[root@oldboy-king-v3 oldboy]# sed '3i 999,lidao007,UFO' sed.txt
101,oldboy,CEO
102,oldbao,CTO
999,lidao007,UFO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO[root@oldboy-king-v3 oldboy]# sed '3c 999,lidao007,UFO' sed.txt
101,oldboy,CEO
102,oldbao,CTO
999,lidao007,UFO
104,yy,CFO
105,feixue,CIO
110,oldboy,COCO