sed命令相关理论

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,又被称为模式空间,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。

sed命令在处理文件的时候先要找到用户指定的位置,如用户想使用sed替换第二行的内容为mars,那么它首先需要定位第二行在哪里。默认情况下,sed 命令会作用于文本数据的所有行。如果只想将命令作用于特定行或某些行,则必须写明地址部分[address]。表示的方法有以下 2 种:

  1. 以数字形式指定行区间:
    sed 会将文本流中的第一行编号为 1,然后继续按顺序为接下来的行分配行号。在脚本命令中,指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。
sed '2,3s/dog/cat/' test.sh  // 其中的数字2,3就是定位第2、3行,该命令其他的部分后续会进行详细说明
  1. 用文本模式指定具体行区间;
    sed 允许指定文本模式来过滤出命令要作用的行,需要注意的是该文本需要用正斜线/包起来。
sed '/demo/s/bash/csh/' /etc/passwd  // 寻找到以含有demo那一行数据,该命令其他的部分后续会进行详细说明

sed命令基本语法及举例

基本语法如下:

sed 选项参数 命令模式 file

现象参数如下表:

选项参数功能
-e直接在指令列模式上进行sed的工作编辑
-f该选项会将其后文件中的脚本命令添加到已有的命令中
-n默认情况下,sed 会在所有的脚本执行完毕后,会自动输出处理后的内容,而该选项会屏蔽自动输出,需使用 print 命令来完成输出
-i此选项会直接修改源文件

命令参数如下表:

命令功能描述
a新增,a的后面可以接子串,在下一行出现,前面接数字即新增在那一行的之后
d删除,前面加数字即代表删除那一行
s查找并替换
n1~512 之间的数字,表示指定要替换的字符串出现第几次时才进行替换,例如,一行中有 3 个 A,但用户只想替换第二个 A,这时就用到这个标记
g对数据中所有匹配到的内容进行替换,如果没有 g,则只会在第一次匹配成功时做替换操作。例如,一行数据中有 3 个 A,则只会替换第一个 A
yy/inchars/outchars/,处理单个字符,对 inchars 和 outchars 值进行一对一的映射
p会打印与替换命令中指定的模式匹配的行。此标记通常与 -n 选项一起使用
w file将缓冲区中的内容写到指定的 file 文件中
&用正则表达式匹配的内容进行替换
\n匹配第 n 个子串,该子串之前在 pattern 中用 () 指定
\转义(转义替换部分包含:&、\ 等)

具体使用如例:
关于添加脚本命令a/i

sed "2a guojia" test.sh  // 将“guojia”增添在test.sh的第二行
sed "2i guojia" test.sh  // 将“guojia”增添在test.sh的第二行

关于替换脚本命令c/s

sed '3c changed' test.sh  // 针对某一行,修改替换第三行的内容
sed "s/wo/ni/g" test.sh  // 针对某串字符将文件中的wo全部改为ni

关于打印命令p

sed -n '/3/{ p s/line/test/p }' test.sh  // 首先打印第三行内容,然后替换第三行的line为test再次打印

关于删除d

sed 'd' test.sh  // 缓冲区中删除内容,并不会删除源文件中的内容
sed '3d' test.sh  // 删除文件内容中的第 3 行 
sed '2,3d' test.sh // 删除文件内容中的第 2、3 行
sed '/1/,/3/d' test.sh  // 删除文件内容中的第 1-3行
sed '3,$d' test.sh  // 删除文件内容中第 3 行开始的所有的内容

关于读文件r

sed '3r test2.txt' test.sh  // 把test2文件内容哈入到test文件的第三行之后输出

关于退出文件q

sed '/number 1/{ s/number 1/number 0/;q; }' test.sh   // 匹配到 number 1 时,将其替换成 number 0,然后直接退出。

sed命令扩展知识

1 sed多行命令

我们知道sed命令基本上只是针对单行进行操作,但是,有时我们需要对跨多行的数据执行特定操作。假设我们想要在文件中匹配的字符串mars concern刚好位于文件内容的两行,这时使用sed命令似乎无法满足我们的需求。 幸运的是,sed 命令的设计人员已经考虑到了这种情况,并设计了对应的解决方案。sed 包含了三个可用来处理多行文本的特殊命令,分别是:

  1. Next 命令(N):将数据流中的下一行加进来创建一个多行组来处理。
  2. Delete(D):删除多行组中的一行。
  3. Print(P):打印多行组中的一行。

如:

sed '/first/{ N ; s/\n/ / }' test.sh // 查找含有单词 first 的那行文本,用N命令将下一行也放入缓冲区中(之间用换行符分隔),把两行当成一行来处理,然后用替换命令s将换行符替换成空格。
sed '/^$/{N ; /header/D}' test.sh // 查找空白行,用 N 命令来将下一文本行添加到缓冲区。此时如果缓冲区的内容中含有单词 header,则 D 命令会删除缓冲区中的第一行,即第一个换行符(包括换行符)之前的内容。

2 sed保持空间

以上我们所提到的sed 命令处理的基本上是缓冲区中的内容,其实这里的缓冲区,应称为模式空间。但是模式空间并不是 sed 命令保存文件的唯一空间。sed 还有另一块称为保持空间的缓冲区域,它可以用来临时存储一些数据。

  1. 模式空间(pattern space):是sed软件从文本读取一行文本然后存入的缓冲区(这个缓冲区是在内存中的),然后使用sed命令操作模式空间的内容。
  2. 保持空间(hold space):是sed软件另外一个缓冲区,用来存放临时数据,也是在内存中,但是模式空间和保持空间的用途是不一样的。Sed可以交换保持空间和模式空间的数据,但是不能在保持空间上执行普通的sed命令,也就是说我们可以在保持空间存储数据。

保持空间最直接的作用是,一旦我们将模式空间中所有的文件复制到保持空间中,就可以清空模式空间来加载其他要处理的文本内容。

相关命令如下:

命令功能
h将模式空间中的内容复制到保持空间
H将模式空间中的内容附加到保持空间
g将保持空间中的内容复制到模式空间
G将保持空间中的内容附加到模式空间
x交换模式空间和保持空间中的内容

大家可以思考一下以下命令的作用:

 sed -n '/first/{h;p;n;p;g;p;}' test.sh
  1. 过滤出含有单词first的行
  2. h 命令将该行放到保持空间
  3. p 命令打印模式空间内容(即含first的那一行)
  4. n 命令提取数据流中的下一行(匹配到first的下一行),并将它放到模式空间
  5. p 命令打印模式空间的内容
  6. g命令将保持空间的内容(即含first的那一行)放回模式空间,替换当前文本
  7. p 命令打印模式空间的当前内容,即含first的那一行

3 sed-b分支命令

通常,sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似。语法如下:

[address]b [label]

address 参数(在最前面的内容中我们介绍过该值的两种形式)决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。
我们使用下例分析以下-b的作用:

sed '{/first/b jump1 ; s/This is the/No jump on/ :jump1  s/This is the/Jump here on/}' test.sh

如果文本行中出现了 first,程序的执行会直接跳到 jump1 标签之后的脚本行。如果分支命令的模式没有匹配,sed 会继续执行所有的脚本命令。

4 sed-t测试命令

测试命令也会更改执行流程,会根据 s 替换命令的结果,如果匹配并替换成功,则脚本的执行会跳转到指定的标签;反之,t 命令无效。测试命令使用与分支命令相同的格式:

[address]t [label]

例如我们看如下命令:

sed '{s/first/matched/ t  s/This is the/No match on/ }' test.sh

即是查找模式文本first,如果匹配并替换成功,命令会直接跳过后面的替换命令;但是如果第一个没有替换成功,就执行第二个s/This is the/No match on/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐