介绍
Linux sed 命令是利用脚本来处理文本文件,全称 ”Stream Editor“,是一种流编辑器,它也被称为行编辑器,因为它在实现文本处理时是逐行进行处理的。
sed 可依照脚本的指令来处理、编辑文本文件。
sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。
模式空间
sed 命令会从文件读取一行并将该行放入模式空间,然后在模式空间中看该行是否符合我们指定的条件,如果符合或者说是被匹配到了那么就对该行做相应处理。
保持空间
sed 命令的保持空间相当于仓库,在模式空间对数据进行处理时,可以把数据临时存储到保持空间;作为模式空间的一个辅助临时缓冲区,但又是相互独立,可以进行交互,命令可以寻址模式空间但是不能寻址保持空间。可以使用高级命令 h
、H
、g
、G
与模式空间进行交互。
基本使用
set [option]... [script] [input_file] ...
option:
-n:静默模式,不把处理后的结果输出到屏幕;
-e:多点编辑;
-f <file>:从文件中读取编辑脚本;
-r:支持正则表达式;
-i:在原文件中编辑,而不是输出到屏幕;
script:sed 脚本;
input_file:处理的文件,可以有多个,处理完第一个就会接着处理第二个;
sed
中也可以使用地址定界的方式来匹配文本,和 VIM 中底行模式相同,可参考【地址定界】。
d 删除
d
命令用来删除匹配到的内容。
例 1:删除 /etc/fstab
中以 UUID
开头的行。
$ sed '/^UUID/d' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
例 2 :删除 /etc/fstab
中所有的空白行和以 #
开头的行。
$ sed '/^[$#]/d' /etc/fstab
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
例 3:把 /etc/fstab
中删除 1~3 行后的内容输出到屏幕。
$ sed '1,3d' /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
p 打印
p
命令用来显示模式空间的内容。
例 1:显示 /etc/fstab
中以 UUID
开头的行。
$ sed '/^UUID/p' fstab -n
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
因默认会显示处理结果文本,所以这里要使用
-n
选项开启静默模式,仅显示通过p
命令输出的行。
a 追加文本
a \<text>
命令可以把给定的 text
文本追加到每一个符合条件的行后面。
例 1:给 /etc/fstab
中每一个以 UUID
开头的行后面加入 # hello sed
文本。
$ sed '/^UUID/a \# hello sed' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
# hello sed
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
# hello sed
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
# hello sed
追加的内容可使用
\n
作换行符,从而实现多行追加。
i 插入文本
i \<text>
命令可以把给定的 text
文本插入到每一个符合条件的行前面。
例 1:给 /etc/fstab
中每一个以 UUID
开头的行的前面插入一个 # hahaha
。
$ sed '/^UUID/i \# hahaha' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
# hahaha
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
# hahaha
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
# hahaha
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
c 替换文本
c \<text>
命令替换每一个符合条件的行为给定的 text
文本。
例 1:把 /etc/fstab
中每一个以 #
开头的行替换为 # 这是注释行
。
$ sed '/^#/c \# 这是注释行' /etc/fstab
# 这是注释行
# 这是注释行
# 这是注释行
# 这是注释行
# 这是注释行
# 这是注释行
# 这是注释行
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
w 写入文件
w <file>
命令可以将每一个符合条件的行另存到 file
指定的文件中。
例 1:把 /etc/fstab
中每一个以 UUID
开头的行保存到 fstab_uuid.txt
中。
$ sed '/^UUID/w fstab_uuid.txt' -n /etc/fstab
$ cat fstab_uuid.txt
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
= 显示行号
=
命令可以在每一个符合条件的行的上方添加一个行号显示。
例 1:在 /etc/fstab
中的每一个以 UUID
开头的行的上方显示一个行号。
$ sed '/^UUID/=' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
9
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
10
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
11
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
r 读取文件
r <file>
命令能够把指定文件中的内容追加到的每一个符合条件的行后。
例 1:把 /etc/resolv.conf
中的内容追加到 /etc/fstab
中第 2 行的后面。
$ sed '2r /etc/resolv.conf' /etc/fstab
#
# Generated by NetworkManager
nameserver 10.0.1.254
# /etc/fstab
# Created by anaconda on Tue Dec 3 20:47:57 2019
#
# 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
#
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
! 地址定界取反
在命令前使用 !
可对地址定界取反。
例 1:删除 /etc/fstab
中不以 ^UUID
开头的行。
$ sed '/^UUID/!d' /etc/fstab
UUID=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
UUID=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
UUID=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
同
sed '/^UUID/p' fstab -n
效果相同。
s 查找替换
格式同 VIM 中的相同,s/被替换的内容/新内容/选项
,分隔符也可不使用 /
自己定义。
选项有如下即可:
g
:默认只替换每行查找过程中第一次出现的内容,可通过g
指定选项实现行内全局替换;p
:显示替换成功的行;w <file>
:将匹配替换后的结果保存到file
中;
例 1:替换 /etc/fstab
中所有 UUID
为 uuid
并仅显示被替换的行。
$ sed 's/UUID/uuid/gp' /etc/fstab -n
uuid=f67055b0-03ba-4e15-a1e1-8124505d1d31 / xfs defaults 0 0
uuid=76c059b7-1c58-429b-8936-ac34a749976d /boot xfs defaults 0 0
uuid=2702f1d8-3154-4194-a25f-50c304d99e67 swap swap defaults 0 0
例 2:给 /etc/passwd
中匹配 r..t
的内容后加上 er
,且仅显示修改的行。
$ sed 's/r..t/&er/gp' /etc/passwd -n
rooter:x:0:0:rooter:/rooter:/bin/bash
operator:x:11:0:operator:/rooter:/sbin/nologin
ftp:x:14:50:FTP User:/var/fterp:/sbin/nologin
dockerrooter:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
进阶命令
在上面基本使用中只用到了模式空间,而下面就要介绍一下 sed 的保持空间的使用。
关于保持空间的操作要使用到下面几个命令:
h
:把模式空间的内容覆盖至保持空间,原保持空间的内容将被清除;H
:把模式空间的内容追加至保持空间,而不覆盖原有保持空间内容;g
:从保持空间中取出内容覆盖至模式空间,原模式空间的内容将被清除;G
:从保持空间中取出内容追加至模式空间,而不覆盖原有模式空间内容;x
:把模式空间的内容与保持空间的内容互换;n
:读取匹配到的行的下一行到模式空间;N
:追加匹配到的行的下一行到模式空间;d
:删除模式空间中的行;D
:删除多行模式空间中的所有行;
为方便后面测试创建测试文件 test.txt
如下:
1 32423dadewarea
2 faewdfaef
3 feaddfae
4 edaded
5 faewdf
6 feawdfeaw
7 eafea
8 deawd
9 daewdw
显示偶数行
$ sed 'n;p' test.txt -n
2 faewdfaef
4 edaded
6 feawdfeaw
8 deawd
多个命令之间可以使用
;
来分隔;
由于没有指定匹配规则,所以所有行都满足条件,每读到一行n
命令就会把下一行覆盖至当前模式空间,所以最后输出的就是偶数行。
显示最后两行
$ sed '$!N;$!D' test.txt
9 daewdw
每读取一行就将下一行追加到模式空间中,如果不是最后一行就删除,所以如果文件是偶数行时,保留的就是最后两行,如果文件是奇数行时,保留的就是最后一行。
逆向显示文件内容
$ sed '1!G;h;$!d' test.txt
9 daewdw
8 deawd
7 eafea
6 feawdfeaw
5 faewdf
4 edaded
3 feaddfae
2 faewdfaef
1 32423dadewarea
在读取第一行时由于保持空间没有内容,所以使用
1!G
指定在第一行时不取保持空间的内容;
在读取最后一行时,由于最后要通过模式空间输出内容,所以使用$!d
指定在最后一行时不清空模式空间的内容;
显示最后一行
$ sed '$!d' test.txt
9 daewdw
不是最后一行就执行删除模式空间的操作,所以最后模式空间中的内容就只剩最后一行。
给每行插入空行
$ sed 'G' test.txt
1 32423dadewarea
2 faewdfaef
3 feaddfae
4 edaded
5 faewdf
6 feawdfeaw
7 eafea
8 deawd
9 daewdw
每读取一行就将保持空间的内容追加至模式空间,而保持空间不存在内容,所以每次追加的就是空行。
合并空白行并给每行插入空行
$ cat test.txt -A
1 32423dadewarea$
2 faewdfaef$
$
$
$
3 feaddfae$
4 edaded $
$
5 faewdf $
$
$
6 feawdfeaw$
7 eafea$
8 deawd$
9 daewdw$
$ sed '/^$/d;G' test.txt
1 32423dadewarea
2 faewdfaef
3 feaddfae
4 edaded
5 faewdf
6 feawdfeaw
7 eafea
8 deawd
9 daewdw
显示奇数行
$ sed 'n;d' test.txt
1 32423dadewarea
3 feaddfae
5 faewdf
7 eafea
9 daewdw
每读取一行就删除下一行,最后只保留了奇数行。
步进
sed
命令可使用 <起始值>~<步长>
来指定步进操作。
显示奇数行:
$ sed '1~2p' -n test.txt
1 32423dadewarea
3 feaddfae
5 faewdf
7 eafea
9 daewdw
显示偶数行:
$ sed '2~2p' -n test.txt
2 faewdfaef
4 edaded
6 feawdfeaw
8 deawd
练习
1、删除 /etc/grub2.cfg
文件中所有以空白开头的行首的空白。
sed 's/^[[:space:]]\+//' /etc/grub2.cfg
2、删除 /etc/fstab
文件中所有以 #
开头,后面至少跟一个空白字符的行的行首的 #
和空白字符。
sed 's/^#[[:space:]]\+//' /etc/fstab
3、echo
一个绝对路径给 sed
命令,取出其基名和目录名。
目录名:
echo `which wget` | sed 's@[^/]\+/\?$@@'
基名:
echo `which wget` | sed -r 's@(^/.*)/(.+)$@\1/@'
评论区