Shell 流编辑器 Sed

本文详细介绍了Linux中的sed编辑器,包括其批处理特性、基本语法、常用选项、子命令如替换、删除、插入等,以及行地址和正则表达式的应用,帮助读者掌握sed的强大文本处理能力。
摘要由CSDN通过智能技术生成

一、sed 介绍
Linux 中,常使用流编辑器 Sed 进行文本替换工作。与交互式编辑器(如vim)不同,Sed 编辑器以批处理的方式来编辑文件,这比交互式编辑器快得多,可以快速完成对数据的编辑修改。
Sed 编辑器会执行以下操作:

  1. 一次从输入中读取一行数据;
  2. 根据所提供的编辑器命令匹配数据;
  3. 按照命令修改流中的数据;
  4. 将新的数据输出到 STDOUT。

在 Sed 编辑器匹配完一行数据后,它会读取下一行数据并重复这个过程,直到处理完所有数据。使用 Sed 命令打开一个 Sed 编辑器。

sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

二、sed 语法
sed [options] edit_commands [file]    # [ ] 中的内容为可选可不选
注意:sed 和 grep 不一样,不管是否找到指定的模式,它的退出状态都是0,只有当命令存在语法错误时,sed的退出状态才是非0
常用选项**

选项功能
-n(silent)使用安静(silent)模式。来自stdin的资料一般都会被列出到屏幕,加上-n后,则只有经过sed处理的行才会被列出
-e(expression)允许多点编辑
-f(file)将sed的动作写在一个文本内,-f filename 则可以执行filename内的sed动作。
-r(regexp)支持扩展正则
-i(in place)直接修改源文件

三、sed 子命令

普通子命令功能
a追加
c修改
i插入
d删除
w将行写入文件
y将字符转换为另一字符
p打印
r读入字符串到文件
q退出sed
=打印当前行号
s替换

子命令取反
! 取反

flag标记

g 单行全局

p 打印

数字 操作到第几个匹配

高级子命令功能
h拷贝pattern space的内容到holding buffer
H追加pattern space的内容到holding buffer
g获得holding buffer中的内容,并替代当前pattern space中的文本
G获得holding buffer中的内容,并追加到当前pattern space的后面
x交换暂存缓冲区与模式空间的内容
n读取下一个输入行,用下一个命令处理新的行而不是用第一个命令
N追加新行到模式空间
P打印模式空间中的第一行
D删除模式空间的第一行,会导致sed从开头重新执行所有子命令

1、定址

默认sed 对文件中的所有行进行编辑。当然,也可以只指定特定的某些行,或者行范围进行流编辑,这需要用到行寻址。所指定的行地址放在子命令之前

[address]commands

数字定址

sed 编辑器将文本流中的每一行都进行编号,第一行的编号为 1 ,后面的按顺序分配行号。通过指定特定的行号,可以选择编辑特定的行

[root@localhost ~]# sed ‘3 s/bin/BIN/g’ /etc/passwd    # 将第3行中所有的 bin 替换成 BIN
[root@localhost ~]# sed ‘2,5 s/bin/BIN/g’ /etc/passwd   # 将第2到5行中所有的 bin 替换成 BIN
[root@localhost ~]# sed ‘10,$ s/bin/BIN/g’ /etc/passwd  # 将第10行到最后一行中所有的 bin 替换成 BIN

正则定址

sed 编辑器允许使用正则过滤出命令要作用的行
/pattern/command

必须使用" / " 将要指定的 pattern 包起来。sed 会寻找匹配文本模式的行,然后对这些行执行编辑命令
[root@localhost ~]# sed -n ‘/root/s/bin/BIN/p’ /etc/passwd # 寻找包含有字符串 root 的行,并将匹配行的 bin 替换为 BIN
与数字寻址一样,也可以使用正则过滤区间来过滤行
[root@localhost ~]# sed ‘/pattern1/,/pattern2/ edit_command’ file

这行命令会在文件 file 中先寻找匹配 pattern1 的行,然后从该行开始,执行编辑命令,直到找到匹配 pattern2 的行。但是需要注意的是,使用文本区间过滤文本时,只要匹配到了开始模式(pattern1),
编辑命令就会开始执行,直到匹配到结束模式(pattern2),这会导致一种情况:一个文本中,先匹配到了一对 pattern1、pattern2,对该文本区间中的文本执行了编辑命令;然后,
在 pattern2 之后又匹配到了 pattern1,这时就会再次开始执行编辑命令,因此,在使用文本区间过滤时要注意这一点

[root@localhost ~]# sed -n ‘/root/,/nologin/ s/bin/BIN/p’ /etc/passwd
root:xx:0:0:root:/root:/BIN/bash
BIN:xx:1:1:bin:/bin:/sbin/nologin
operator:xx:11:0:operator:/root:/sBIN/nologin
games:xx:12:10:games:/usr/games:/sBIN/nologin

2、子命令使用

s 替换

使用 s 命令来进行文本替换操作
[root@localhost ~]# sed ‘s/srcStr/dstStr/’ file

其中,srcStr 为想要替换的文本,dstStr 为将要替换成的文本。使用 s 命令时,sed 编辑器会在一行一行地读取文件 file,并在每行查找文本 srcStr,如果找到了,
则将该处的 srcStr 替换为 dstStr。
/ 字符为界定符,用于分隔字符串(sed 编辑器允许使用其他字符作为替换命令中的字符串分隔符):

[root@localhost ~]# sed ‘s!/bin/bash!/BIN/BASH!’ /etc/passwd # 使用 ! 作为字符串分隔符
[root@localhost ~]# sed ‘s#3#88#g’ datafile

默认,s只会替换掉目标文本在每行中第一次出现的地方。若想要替换掉每行中所有匹配的地方,可以使用替换标记 g。替换标记放在编辑命令的末尾。除了 g 外,还有几种替换标记:

1、数字指明替换掉第几次匹配到的文本,

没有设置这个标记时,默认是替换第一次匹配的文本
[root@localhost ~]# sed ‘s/root/ROOT/2’ /etc/passwd
这行命令将 /etc/passwd 文件中每行的第 2 个 root 替换为 ROOT

2、g 替换所有匹配到的文本
[root@localhost ~]# sed ‘s/root/ROOT/g’ /etc/passwd
这行命令将 /etc/passwd 文件中的 root,全部替换为 ROOT;

3、p 打印与替换命令中指定模式(srcStr)相匹配的行
[root@localhost ~]# sed ‘s/root/ROOT/p’ /etc/passwd
执行这命令,会在 STDOUT 上看到包含有 root 的行被输出了两次,一次是 sed 编辑器自动输出的;另一次则是 p 标记打印出来的匹配行
[root@localhost ~]# sed -n ‘s/root/ROOT/gp’ /etc/passwd    # 将 /etc/passwd 中所有的 root 都替换成 ROOT,并输出被修改的行

d 删除

sed 编辑器使用 d 命令来删除文本流中的特定行。使用 d 命令时,一般需要带上位寻址,以删除指定的行,否则默认会删除所有文本行。
[root@localhost ~]# sed ‘/root/d’ /etc/passwd  # 删除匹配 root 的行

[root@localhost ~]# sed ‘2,$d’ /etc/passwd    # 删除第2到最后一行

[root@localhost ~]# sed ‘3d’ /etc/passwd
[root@localhost ~]# sed ‘3{d;}’ /etc/passwd
[root@localhost ~]# sed ‘3{d}’ /etc/passwd
[root@localhost ~]# sed ‘$d’ /etc/passwd
[root@localhost ~]# sed ‘/north/d’ /etc/passwd
[root@localhost ~]# sed ‘/sout/d’ /etc/passwd

插入追加修改文本

sed 编辑器使用 i 命令来向数据流中插入文本行,使用 a 命令来向数据流中附加文本行。其中i 命令会在指定行前增加一个新行;a 命令会在指定行后增加一个新行。

注意这两个命令都不能在单行上使用(即不是用来在一行中插入或附加一段文本的),只能指定插入还是附加到另一行。

[root@localhost ~]# sed ‘[address][i | a] newline’ file
[root@localhost ~]# sed ‘i\Insert a line behind every line’ /etc/passwd      # 向数据流的每一行前面增加一个新行,新行的内容为 \ 后面的内容
[root@localhost ~]# sed ‘1i\Insert a line behind the first line’ /etc/passwd   # 在数据流的第一行前面增加一个新行
[root@localhost ~]# sed ‘3a\Append a line after the third line’ /etc/passwd # 在数据流的第三行后面增加一个新行    
[root@localhost ~]# sed ‘$a\Append a line in the last line’ /etc/passwd      # 在数据流的最后一行后面增加一个新行

使用命令 c 可以将数据流中的整行文本修改为新的行,与插入、附加操作一样,这要求在 sed 命令中指定新的行

[root@localhost ~]# sed ‘[address][c] newtext’ file
[root@localhost ~]# sed ‘3 c\New text’ /etc/passwd     # 将数据流中第三行的内容修改为 \ 后面的内容
[root@localhost ~]# sed ‘/root/ c\New text’ /etc/passwd  # 将匹配到 root 的行的内容修改为 \ 后面的内容
[root@localhost ~]# sed ‘2,4c\New text’ /etc/passwd     # 将第2到4行的内容修改为 \ 后面的内容,但是不是逐行修改,而是会将这之间的 3 行用一行文本来替代

y 逐字符转换

shell
[address]y/inchars/outchars/
转换命令会对 inchars 和 outchars 的值进行一对一的映射。inchars 中的第一个字符会被转换成 outchars 中的第一个字符;inchars 中的第二个字符会被转换成 outchars 中的第二个字符;… 直到处理完一行。如果 inchars 和 outchars 的长度不同,则 sed 编辑器会产生一个错误消息。举个例子:

[root@localhost ~]# echo abcdefggfedcba | sed 'y/acg/ACG/'
 AbCdefGGfedCbA

w 保存数据到文件
[address]w filename

[root@localhost ~]# sed ‘1,2w test.txt’ /etc/passwd
[root@localhost ~]# sed -n ‘s/root/ROOT/g w change.txt’ /etc/passwd # 将 /etc/passwd 中所有的 root 都替换成 ROOT,并将被修改的行保存到文change.txt 中去
该语句将数据流的第 1、2 行写入文件 test.txt 中去。

r 从文件中读取数据
可以使用 r 命令来将一个文本中的数据插入到数据流中去,与普通的插入命令 i 类似,这也是对行进行操作的,命令格式如下:

[address]r filename

filename 为要插入的文件。r 命令常结合行寻址使用,以将文本插入到指定的行后面

[root@localhost ~]# sed ‘3 r test.txt’ /etc/passwd
这句话将文件 test.txt 中的内容插入到数据流第三行后面去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值