sed 命令详解

4.1 工作原理

sed 即 Stream EDitor,和 vi 不同,sed是行编辑器

  • Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行
  • 每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间pattern space
  • 一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象

=

4.2 命令选项⭐

sed [option]... 'script ; script ;...'  file...

其中 "script" = 地址&动作
多个script表示 可以同时进行多个script操作,用 ; 隔开(如'2p;5p')

-n   不输出模式空间内容到屏幕,即不自动打印(核心选项)
-e   多点编辑!!!适合用于编辑配置文件
-r/E 使用扩展正则表达式(扩展)
-i	 直接编辑不备份
-i.bak  '先备份文件并编辑源文件'
-f /PATH/SCRIPT_FILE 从指定文件中读取编辑脚本

=

4.2.1 script 地址锚定
  • 可组合使用,自定义指定想要的行
  • 指定具体行号不需要斜线!!!
1.不给地址:对全文进行处理
=======================
2.单地址:
 #:         指定的行
 $:         最后一行
 /pattern/: 能被此模式匹配到的每一行(正则)
=========================================
3.范围地址:
 #, #             第几行到第几行
 #,+#             从第几行到后续几行
 /pat1/,/pat2/    从 【pat1匹配到的行】 到 【pat2匹配到的行】
 #,/pat/          从 【第#行】 到 【pat匹配到的行】
=======================================================
4. 步进:~
  1~2 奇数行
  2~2 偶数行

=

4.2.2 script 处理命令
  • 只能单独使用!即一次只能进行一种处理动作
  • 特殊情况:不输入命令,表示只匹配行,不进行其他操作
# 常用:
p 打印当前模式空间内容,追加到默认输出之后
d 删除模式空间匹配的行,并立即启用下一轮循环(取反)

# 注意:以下[\]是可选占位符。。。若不写,此处也要留出空格
a\text 在指定行下一行插入文本行,'支持使用\n实现多行追加
i\text 在指定行上一行插入文本行
c\text '替换指定行内容'为单行或多行文本
===================================================

# 不常用:
w /path/file 保存模式匹配的行至指定文件
r /path/file 读取指定文件的文本至模式空间中匹配到的行后

=  只显示匹配到的'行号'
!  模式空间中匹配行取反处理
==================================================

# 说明:整个 s/// 是一个script命令! 前面还可以加上地址限定条件:'/pat/s/pat/string/修饰符'
s/pattern/string/修饰符 
查找替换,支持使用其它分隔符:s@@@,s###
    # 修饰符:
	g 行内全局替换(一行之内可能有多处符合要求)
	p 显示替换成功的行  '核心动作'
	w /PATH/FILE 将替换成功的行保存至文件中

=

=

4.2.3 范例汇总

1范例:可接受标准输入

[root@centos8 ~]# sed ''  表示script内容为空
ddd
ddd
dddddddd
dddddddd
fffffffffffffffffff
fffffffffffffffffff     # 使用ctrl+D退出
[root@centos8 ~]# 

=

1 原理演示⭐

2范例:模式空间输出原理

# sed 默认相当于echo一次,'p'再次打印,-n不打印
[root@centos8 ~]# sed '' /etc/issue		# 正常输出原文
\S
Kernel \r on an \m

#---------------
[root@centos8 ~]# sed -n '' /etc/issue	 # 不输出内容
[root@centos8 ~]# sed  'p' /etc/issue	 # 每行重复
\S
\S
Kernel \r on an \m
Kernel \r on an \m


#---------------
[root@centos8 ~]# sed -n 'p' /etc/issue   # 加一减一还是正常输出原文
\S
Kernel \r on an \m

[root@centos8 ~]# 

=

2 指定行

3范例:输出指定的【某一行】

[root@centos8 ~]# sed -n '1p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@centos8 ~]# sed -n '2p' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@centos8 ~]# sed -n '3p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin

[root@centos8 ~]# ip a | sed -n '9p' 
    inet 10.0.0.8/24 brd 10.0.0.255 scope global noprefixroute ens160

=

4范例:输出指定的【连续几行】

[root@centos8 ~]# seq 9 | sed -n '2,5p'
2
3
4
5
[root@centos8 ~]# seq 9 | sed -n '2,+2p'
2
3
4
[root@centos8 ~]# seq 9 | sed -n '7,$p'
7
8
9

=

5范例:取奇数或偶数行

[root@centos8 ~]# seq 8 | sed -n '1~2p'
1
3
5
7
[root@centos8 ~]# seq 8 | sed -n '2~2p'
2
4
6
8

# 使用命令 d 表示删除匹配到的行,效果是取反!!!(不能再加选项 -n)
[root@centos8 ~]# seq 6 | sed -n '1~2d'
[root@centos8 ~]# seq 8 | sed -n '1~2d'  因为d已经删除模式空间内容,再加-n就删除了原本的echo效果
[root@centos8 ~]# seq 8 | sed  '1~2d'
2
4
6
8
[root@centos8 ~]# seq 8 | sed  '2~2d'
1
3
5
7

=

3 实现 grep

6范例:使用/pattern/实现【特定行】的匹配(类似grep)

[root@centos8 ~]# ip a | sed -n '/inet/p'     # 此处 p 是script命令!!
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
    inet 10.0.0.8/24 brd 10.0.0.255 scope global noprefixroute ens160
    inet6 fe80::e016:ece6:7e36:e2ec/64 scope link noprefixroute 
    
[root@centos8 ~]# df|sed -n '/^\/dev\/sd/p'   # 此处 p 是script命令!!
/dev/sda2      104806400 3728680 101077720   4% /
/dev/sda5       52403200  398892  52004308   1% /data
/dev/sda1         999320  106688    823820  12% /boot

=

4 多点编辑⭐

7范例:多点编辑(两种方式)

# 取出除3、5、7以外的行
[root@centos8 ~]# seq 8 | sed -e '3d' -e '5d' -e '7d'
1
2
4
6
8

# 取出除1、2、5以外的行
[root@centos8 ~]# seq 8 | sed '1d;2d;5d'
3
4
6
7
8

注:以上都是以打印命令 p 进行演示,换成删除命令 d 都同理

如:批量删除指定行

sed '/^$/d' file   删除所有空行
sed '1,10d' file   删除1~10行

=

=

4.3 sed 核心功能

对文件内容进行编辑!同时可对原文件进行备份【核心功能】

  • 可选择是否备份,直接 -i表示修改;-i.bak表示备份并修改(注意格式:-i 后面直接紧挨着指定后缀
  • 应该注意到,此选项是确实修改了文件内容。其余选项都是将处理结果输出,原文件并不改变
  • -i与其他选项一起使用时,必须位于最后一个(常用-ri)!!!(类似tar xvff必须在最后)
  • 尽量不要与-n合用。。。否则容易改错文件

=

1 指定范围备份
[root@centos8 ~]# cat seq.log 
1
2
3
4
5
6

[root@centos8 ~]# sed -i.bak '2d;4d;5d' seq.log
[root@centos8 ~]# ll se*
-rw-r--r--. 1 root root  6 Aug 11 11:45 seq.log
-rw-r--r--. 1 root root 12 Aug 11 11:44 seq.log.bak  # 备份成功

[root@centos8 ~]# cat seq.log.bak 
1
2
3
4
5
6
[root@centos8 ~]# cat seq.log
1
3
6

=

2 编辑文件内容

输出编辑后的内容【核心功能】

# 只显示非#开头的行
[root@centos8 ~]# sed -n '/^#/!p' /etc/fstab 

UUID=3d1ad34e-cc80-4047-9167-474bd4dfc5a5 /                       xfs     defaults        0 0
UUID=ed944ea3-8ecd-43f6-af42-b1da086e778c /boot                   ext4    defaults        1 2
UUID=8c8df88e-0a9e-494f-831f-8abffc065a4e /data                   xfs     defaults        0 0
UUID=c47e4725-5b77-4d3f-8842-60e5689d45cc swap                    swap    defaults        0 0

注:'/^#/!p''/^[^#]/p'逻辑相同,但后者会过滤掉空行

# 删除所有以#开头的行
[root@centos8 ~]# sed '/^#/d' fstab 

UUID=3d1ad34e-cc80-4047-9167-474bd4dfc5a5 /                       xfs     defaults        0 0
UUID=ed944ea3-8ecd-43f6-af42-b1da086e778c /boot                   ext4    defaults        1 2
UUID=8c8df88e-0a9e-494f-831f-8abffc065a4e /data                   xfs     defaults        0 0
UUID=c47e4725-5b77-4d3f-8842-60e5689d45cc swap                    swap    defaults        0 0

=

3 插入与替换

在匹配到的行上下插入新行,或替换之【核心功能】

sed '/root/a\superman' /etc/passwd  在匹配行的下一行插入新一行,内容为superman
sed '/root/i\superman' /etc/passwd  在匹配行的上一行插入新一行,内容为superman
sed '/root/c\superman' /etc/passwd  将匹配到的行内容替换为superman

# 注意:aic之后的 \ 可省略,但必须留出这个位置的空格!!!!!

注:【nl命令】对文本逻辑排序,显示行号
[root@centos8 ~]# nl /etc/passwd|sed '2a \tea'
     1	root:x:0:0:root:/root:/bin/bash
     2	bin:x:1:1:bin:/bin:/sbin/nologin
tea
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
..........

[root@centos8 ~]# nl /etc/passwd|sed '2c tea'   # 省略斜线也可
     1	root:x:0:0:root:/root:/bin/bash
tea
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
..........

=

4 -i误操作演示
# 文件caokunzi内容很多,现在只想把 ssl 替换为caokunzi

# 1 查看原始内容
[root@jacklee ~]#grep -n ssl caokunzi
29:    listen 443 ssl;
32:    ssl_certificate /etc/nginx/ssl/5267479__kmelearning.com.pem;
33:    ssl_certificate_key /etc/nginx/ssl/5267479__kmelearning.com.key;
34:    ssl_session_timeout 5m;

# 2 测试修改
[root@jacklee ~]#sed -n s/ssl/caokunzi/p caokunzi 
    listen 443 caokunzi;
    caokunzi_certificate /etc/nginx/ssl/5267479__kmelearning.com.pem;
    caokunzi_certificate_key /etc/nginx/ssl/5267479__kmelearning.com.key;
    caokunzi_session_timeout 5m;
    
# 3 此时 -n 与 p 的组合实际上并未修改源文件
[root@jacklee ~]#sed -n s/ssl/caokunzi/p caokunzi && grep -n ssl caokunzi
    listen 443 caokunzi;
    caokunzi_certificate /etc/nginx/ssl/5267479__kmelearning.com.pem;
    caokunzi_certificate_key /etc/nginx/ssl/5267479__kmelearning.com.key;
    caokunzi_session_timeout 5m;
29:    listen 443 ssl;
32:    ssl_certificate /etc/nginx/ssl/5267479__kmelearning.com.pem;
33:    ssl_certificate_key /etc/nginx/ssl/5267479__kmelearning.com.key;
34:    ssl_session_timeout 5m;

# 若使用 -n -i 组合(一种错误的演示)
[root@jacklee ~]#sed -ni s/ssl/caokunzi/p caokunzi
[root@jacklee ~]#cat -n caokunzi 
     1	    listen 443 caokunzi;
     2	    caokunzi_certificate /etc/nginx/ssl/5267479__kmelearning.com.pem;
     3	    caokunzi_certificate_key /etc/nginx/ssl/5267479__kmelearning.com.key;
     4	    caokunzi_session_timeout 5m;
'发现此4行已经修改。但是源文件其他内容都被删除!!!只剩编辑过的4行

#》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
# 正确姿势:
sed -i s/ssl/caokunzi/ caokunzi

--------------------------------
'下列错误的共同点:若不加 -i 时会输出什么,则加上 -i 之后源文件就会被修改成什么
# 错误1:(-n 和 p)与 -i 共用
  导致后果:源文件只剩编辑行
  
# 错误2:(-n)与 -i 共用
  导致后果:源文件所有内容清空
  
# 错误3:(p)与 -i 共用
  导致后果:编辑成功,但是所有编辑行都在原位置下方被复制了新的一行

=

=

4.4 特殊命令:搜索替换 s / / /⭐

1 重要说明
  • 搜索替换只是一个script命令,前面还可以被地址条件限制
    但实际使用一般不限定地址,表示全文搜索匹配并进行替换
  • script命令在一次操作中只能有一个,但是命令 s/// 的修饰符g/p可同时使用(与选项 -n 配合)!!!
2 格式详解
s/pattern/string/修饰符 
查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
    替换修饰符:
	g 行内全局替换	'一行之内可能有多处匹配,不加 g 表示只处理第一处'
	p 输出替换成功的行
	w /PATH/FILE 将替换成功的行保存至文件中
	
# 注意区别:s///是一个script命令,与 p 是同级别的命令(命令p表示打印模式空间内容)
# 但由于script命令只能有一个,为了不影响输出功能,为s///设置了一个修饰符p,作为命令p的填补

=

3 用法演示(包括 & )
# 常规用法:
# 将文件example全部内容中的test替换为mytest
sed 's/test/mytest/g' example    # 也可表示为's/test/my&/'(而且是全局替换)

上述命令为什么能实现全文处理:
	因为没限定地址:处理每一行
	因为修饰符g:每一行的每一处都不放过
-------------------------------------------------------------------------
-------------------------------------------------------------------------
#【字符 & 的用法】
# 对有root的行 的第一个root 的后方追加superman
sed -n 's/root/&superman/p' /etc/passwd 

# 对有root的行 的第一个root 的前方追加superman
sed -n 's/root/superman&/p' /etc/passwd 
-------------------------------------------------------------------------
-------------------------------------------------------------------------
#【编辑与备份】
# 将文件 pets 中的所有dog换为cat ,所有hi换为lo ,并输出编辑后的全文【未修改内容】
sed -e 's/dog/cat/g' -e 's/hi/lo/g' pets 

# 将文件 pets 备份为pets.bak,且所有dog换为cat,并输出编辑后的全文【备份并修改内容】
sed -i.bak  's/dog/cat/g' pets

=

4 重要范例⭐

帮助理解 -n 与修饰符 p 的关系(与命令 p 如出一辙)

# 替换并输出全文:
[root@CentOS8 ~]#sed 's/UUID/zhubazi/' fstab 

#
# /etc/fstab
# Created by anaconda on Mon Sep 28 03:51:16 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
zhubazi=2452b617-9a10-488d-bc1e-074d216be0b4 /                       xfs     defaults        0 0
zhubazi=f74fb060-143a-40a7-b53e-6e32250d5660 /boot                   ext4    defaults        1 2
zhubazi=a5ce2733-7c85-47ab-8db0-7a182668ead7 /data                   xfs     defaults        0 0
zhubazi=849b755d-9106-4d9c-86d2-4e559c342356 swap                    swap    defaults        0 0

#》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
# 替换并输出全文,且匹配行全部重复(未使用 -n 的结果)
[root@CentOS8 ~]#sed 's/UUID/zhubazi/p' fstab 

#
# /etc/fstab
# Created by anaconda on Mon Sep 28 03:51:16 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
zhubazi=2452b617-9a10-488d-bc1e-074d216be0b4 /                       xfs     defaults        0 0
zhubazi=2452b617-9a10-488d-bc1e-074d216be0b4 /                       xfs     defaults        0 0
zhubazi=f74fb060-143a-40a7-b53e-6e32250d5660 /boot                   ext4    defaults        1 2
zhubazi=f74fb060-143a-40a7-b53e-6e32250d5660 /boot                   ext4    defaults        1 2
zhubazi=a5ce2733-7c85-47ab-8db0-7a182668ead7 /data                   xfs     defaults        0 0
zhubazi=a5ce2733-7c85-47ab-8db0-7a182668ead7 /data                   xfs     defaults        0 0
zhubazi=849b755d-9106-4d9c-86d2-4e559c342356 swap                    swap    defaults        0 0
zhubazi=849b755d-9106-4d9c-86d2-4e559c342356 swap                    swap    defaults        0 0

#》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
#【替换但不输出处理结果】此操作无意义!!!(因为只有 -i 才能真正修改内容)
sed -n 's/UUID/zhubazi/' fstab

#》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
# 替换且只输出匹配行(-n 与 p 组合)
[root@CentOS8 ~]#sed -n 's/UUID/zhubazi/p' fstab 
zhubazi=2452b617-9a10-488d-bc1e-074d216be0b4 /                       xfs     defaults        0 0
zhubazi=f74fb060-143a-40a7-b53e-6e32250d5660 /boot                   ext4    defaults        1 2
zhubazi=a5ce2733-7c85-47ab-8db0-7a182668ead7 /data                   xfs     defaults        0 0
zhubazi=849b755d-9106-4d9c-86d2-4e559c342356 swap                    swap    defaults        0 0

4.5 扩展正则的sed运用

1 取IP

从命令ip a取IP地址:(9表示匹配第9行)

'至少一个非数字,接(一个以上数字或.连续出现),接任意内容
[root@centos8 ~]#ip a | sed -nr "9s/[^0-9]+([0-9.]+).*/\1/p"
10.0.0.8

'以至少一个非数字开头,接(一个以上数字或.连续出现),接任意内容   此方法可简化为1
[root@centos8 ~]#ip a | sed -nr '9s/^[^0-9]+([0-9.]+).*$/\1/p'
10.0.0.8

最佳:'至少一个非数字,接(连续出现的7~15个数字或.),接任意内容   
[root@centos8 ~]#ip a | sed -nr '9s/[^0-9]+([0-9.]{7,15}).*/\1/p' 
10.0.0.8

'利用具体内容前后夹逼
[root@centos8 ~]#ip a | sed -nr '9s/(.*inet )([0-9].*)(\/.*)/\2/p' 
10.0.0.8

'使用两次 s///的空白替换(删除)功能,前后夹逼删除
[root@centos8 ~]#ip a | sed -n '9s/.*inet //;9s/\/.*//p'    #不必句首句尾锚定
10.0.0.8 
[root@centos8 ~]#ip a | sed -n '9s/.*inet //p' | sed -n 's/\/.*//p' #管道后只剩一行,不需9s
10.0.0.8 

=

2 取dirnamebasename
'关键: [^/]+  至少一个不是 / 开头的字符(从左往右抓)
[root@centos8 ~]# echo /etc/sysconfig/network-scripts/ | sed -nr 's#(^/.*/)([^/]+/?)#\1#p'
/etc/sysconfig/
[root@centos8 ~]# echo /etc/sysconfig/network-scripts/ | sed -nr 's#(^/.*/)([^/]+/?)#\2#p'
network-scripts/

=

3 取文件的前缀和后缀
'关键:后缀中没有 字符.
[root@centos8 ~]# echo a.c-d.345.gz|sed -nr 's/(.+)\.([^.]+)/\1/p'
a.c-d.345
[root@centos8 ~]# echo a.c-d.345.gz|sed -nr 's/(.+)\.([^.]+)/\2/p'
gz

'使用grep
[root@centos8 ~]# echo a.c-d.345.gz|grep -Eo '.*\.'
a.c-d.345.  #不够完美
[root@centos8 ~]# echo a.c-d.345.gz|grep -Eo '[^.]+$'
gz

=

4 去掉所有注释和空行
sed  -r  '/^(#|$)/d'  /file
sed  -r  '/^#|^$/d'   /file

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux的sed命令是一个用于文本处理的强大工具。它可以根据指定的编辑命令对输入文件进行操作,并输出结果。sed命令的基本语法如下: sed [选项] sed编辑命令 输入文件 其中,选项是可选的,用于控制sed命令的行为。sed编辑命令是指对文本进行操作的具体命令,可以是单个命令,也可以是多个命令组合在一起。输入文件是要进行处理的文本文件。 sed命令还支持通过管道将shell命令的输出作为输入进行处理,具体语法如下: shell命令 | sed [选项] sed编辑命令 此外,sed命令还可以通过-f选项指定一个sed脚本文件来进行处理,具体语法如下: sed [选项] -f sed脚本文件 输入文件 在使用sed命令时,还可以通过使用一些小技巧来实现特定的功能。例如,可以使用命令连接符";"来输出多行不连续的内容。例如,以下命令会输出passwd文件中的第1行、第3行和第5行: sed -n '1p;3p;5p' passwd 这样,你就能够根据需要使用sed命令来处理文本文件,并实现各种需要的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【Linux篇】sed命令详解](https://blog.csdn.net/weixin_45842494/article/details/124699219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Linux - sed命令详解](https://blog.csdn.net/qq_48391148/article/details/125711532)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值