本文旨在复习Sed文本处理的保持空间[Hold Space]、高级命令、循环标签等

知识储备


  • Sed除了有模式空间外,还有一个保持空间[Hold Space]

  • 模式空间:所有的处理动作、加工都在此处,原材料加工厂,默认动作是打印到终端

  • 保持空间:暂时存放某行内容,存放"行"仓库,无默认动作,通过命令可实现调度

  • 高级命令:所谓的高级命令通常指模式空间 <---> 保持空间 行的交互,如何交换、覆盖、追加

  • Sed循环标签:shell脚本可以用for、while、until循环,而sed是通过调用标签名来实现循环

  • Sed高级命令工作原理如下图

[9-15]Sed文本处理——高级用法_sed

高级命令


前提说明:无论是模式空间、保持空间,是一个大的容器,是可以容纳多行的!!只不过默认情况下我们做的操作都是“覆盖”行为的,所以表现为只有1行,明白了这个概念,再去理解下面的命令。

x交换模式空间与保持空间内容
d删除当前模式空间内容,并进入下一个循环
D删除多行模式空间中的首行,并进入下一个循环
n读取匹配到的下一行至模式空间 [会覆盖模式空间原有的值]
N读取匹配到的下一行至模式空间 [追加到原有内容后]
h复制模式空间内容,到保持空间, 覆盖
H复制模式空间内容,到保持空间, 追加
g复制保持空间内容,到模式空间, 覆盖
G复制保持空间内容,到模式空间, 追加


下面举几个循序渐进的例子:


实验文本1:

1
2
3
4
5
6
7
8


1 A
2 a
3 B
4 b
5 C
6 c
7 D
8 d

例1:使用sed命令隔行打印输出偶数行,即第2行、第4行、第6行、第8行等。

实现代码:

1


sed -n '{n;p}' sed.txt

[9-15]Sed文本处理——高级用法_sed_02

具体分析:

    1. 加工厂送来一批小鲜肉 1 A, 执行加工操作{n;p},首先做n操作

    2. n操作 --> 由于肉不新鲜丢掉,采购下一批2 a,这里会把原来加工厂第一批肉丢掉[覆盖]

    3. p操作 --> 肉质不错,卖给客户,即打印输出到终端上


例2:交换行顺序,预期字母出现先小写再大写,效果为首行2 a 下行1 A

实现代码:

1


 sed -n 'h;n;p;g;p' sed.txt

[9-15]Sed文本处理——高级用法_sed_03

具体分析:

[9-15]Sed文本处理——高级用法_sed_04



实验文本2:

1
2
3
4
5
6
7
8


lance
@mage.com
yaozong
@mage.com
xiejun
@mage.com
mahuteng
@qq.com

例1:找出那些属于mage.com的用户,只显示用户名

实现代码:

1


sed -n -e '/mage/!h' -e '/mage/{x;p}' sed.txt

[9-15]Sed文本处理——高级用法_sed_05

具体分析:

[9-15]Sed文本处理——高级用法_sed_06


例2:整理用qq邮箱地址的人,打印出他们的邮箱地址,输出格式形如lance@mage.com

实现代码:

1


 sed -n -e '/qq.com/!h' -e '/qq.com/{H;x;s/\n//p}' sed.txt

具体分析:

[9-15]Sed文本处理——高级用法_sed_07

看到这里,你可能会对替换命令s/\n//p感到很奇怪,为何替换\n为空多行变1行输出了?

补充说明:模式空间、保持空间中的多行是这样的

[9-15]Sed文本处理——高级用法_sed_08

循环标签


编程语言很大的特点是循环语句实现重复执行,sed中没有for、while、until语句,而是通过定义标签,调用标签来实现循环这种功能的。

一般格式为:

1


sed -n ':标签名 范围1 命令1; /模式/b 标签名' filename

例1:默认s///只能替换每行第一个被匹配的内容,当然如果使用g可以全局替换,这里我们使用标签来替换所有的lance为大写LANCE

1


lance lance lance lance lance lance lance lance

实现代码:

1


sed -n ':again s/lance/Lance/;/lance/b again;p' lance.txt

[9-15]Sed文本处理——高级用法_sed_09

额外说明:标签名调用其实不仅可以使用b,准确来说b调用 t调用 T调用

[9-15]Sed文本处理——高级用法_sed_10