sed高级命令

高级sed命令

sed多行命令

sed 命令的基础功能时, sed 命令都只是针对单行数据执行操作,但是,有时我们需要对多行的数据执行特定操作。如在文本中查找一串字符串,它很有可能出现在两行中,每行各包含其中一部分。这时,如果用普通的 sed 编辑器命令来处理文本,就不可能发现这种被分开的情况。

sed能查看模式空间的多行(就是允许匹配模式扩展到多行上)。

sed 包含了三个可用来处理多行文本的特殊命令,分别是:

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

N多行命令

多行Next (N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间。模式空间最初的内容和新的输入行之间用换行符分隔。在模式空间中嵌入的换行符可以利用转义序列“\n”来匹配。在多行模式空间中,元字符“^”匹配空间中的第一个字条,而不匹配换行符后面的字符。同样,“$”只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符。在执行next命令之后,控制将被传递给脚本中的后续命令。

Next命令与next命令不同,next输出模式空间的内容,然后读取新的输入行。next命令不创建多行模式空间。

下面这个例子演示N命令的功能

[root@master ~]# cat test.txt 
wo shi
cai ao cheng ta die
sha bi
chen shun li
[root@master ~]# 
[root@master ~]# sed '/wo/{N;s/\n/ /}' test.txt 
wo shi cai ao cheng ta die
sha bi
chen shun li
[root@master ~]# 

上面这个例子中,用sed匹配到wo这行的文本在使用N将匹配到文本和下一行加入到模式空间,然后使用替换命令将换行符替换为空格,结果就是在文件中的两行合并成了一行

D 多行删除命令

删除命令(d)删除模式空间的内容并导致读入新的输入行,从而在脚本的顶端重新使用编辑方法。删除命令(D)稍微有些不同:它删除模式空间中直到第一个嵌入的换行符的这部分内容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于模式空间剩余的内容,我们可以编写一个实现查找一系列空行并输出单个空行的脚本,以看看它们之间的区别。下面的语句使用了删除命令(d) :

当遇到一个空行时,下一行就追加到模式空间中。然后试着匹配嵌入的换行符。注意定位元字符^和$分别匹配模式空间的开始处和结束处。下面是测式文件:

[root@master ~]# cat lpl.txt 
EDG 1

FPX 2


RNG 3



LNG 4




WE 5

利用d命令运行结果

[root@master ~]# sed '/^$/{N;/^\n$/d}' lpl.txt 
EDG 1

FPX 2
RNG 3

LNG 4
WE 5
[root@master ~]# 

当有偶数个空行时,所有的空行都会被删除。仅当有奇数个空行时,有一行被保留下来。这是因为删除命令清除的是整个模式空间。一旦遇到第一个空行,就读入下一行,并且两行都被删除。如果遇到第三个空行,并且下一行不为空,那么删除命令就不会被执行,因此空行被输出。如果使用多行Delete命令(是D不是d),就能得到我们想要的结果:

[root@master ~]# sed '/^$/{N;/^\n$/D}' lpl.txt 
EDG 1

FPX 2

RNG 3

LNG 4

WE 5
[root@master ~]# 

多行Delete命令完成工作的原因是,当遇到两个空行时,Delete命令只删除两个空行中的第一个。下一次遍历该脚本时,这个空行将导致另一行被读入模式空间。如果那行不为空,那么两行都输出,因此确保了输出一个空行。换句话说,当模式空间中有两个空行时、只有第一个空行被删除。当一个空行后面跟有文本时,模式空间可以正常输出。

sed 保持空间

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

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

通常,在使用 h 或 H 命令将字符串移动到保持空间后,最终还要用 g、G 或 x 命令将保存的字符串移回模式空间。保持空间最直接的作用是,一旦我们将模式空间中所有的文件复制到保持空间中,就可以清空模式空间来加载其他要处理的文本内容。

由于有两个缓冲区域,下面的例子中演示了如何用 h 和 g 命令来将数据在 sed 缓冲区之间移动。

[root@master ~]# cat test
1
2
11
22
111
222
[root@master ~]# sed '/1/{h;d};G' test
2
1
22
11
222
111
[root@master ~]# 

匹配1,11,111到模式空间然后追加到保存空间,清空模式空间,在将保存空间内容逐行追加到模式空间

[root@master ~]# cat test
1
2
11
22
111
222

[root@master ~]# sed '/1/{h};/2/{H;g}' test
1
1
2
11
11
22
111
111
222

x

[root@master ~]# cat test2
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@lmaster ~]# sed '/header/h;/first/x' test2
This is the header line.
This is the header line.
This is the second data line.
This is the last line.

b 分支命令

通常,sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令(D 命令是个例外,它会强制 sed 返回到脚本的顶部,而不读取新的行)。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似

b 分支命令基本格式为:

[address]b [label]

其中,address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。

需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾,比如:

[root@master ~]# cat test
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@master ~]# sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' test
Is this the header test?
This is the first data line.
This is the second data line.
Is this the last test?
[root@master ~]# 

可以看到,因为 b 命令未指定 label 参数,因此数据流中
的第2行和第3行并没有执行那两个替换命令。

如果我们不想直接跳到脚本的结尾,可以为 b 命令指定一个标签(也就是格式中的 label,最多为 7 个字符长度)。在使用此该标签时,要以冒号开始(比如 :label2),并将其放到要跳过的脚本命令之后。这样,当 sed 命令匹配并处理该行文本时,会跳过标签之前所有的脚本命令,但会执行标签之后的脚本命令。

比如说:

[root@master ~]# sed '{/first/b jump1 ; s/This is the/No jump on/
> :jump1
> s/This is the/Jump here on/}' test
No jump on header line.
Jump here on first data line.
No jump on second data line.
No jump on last line.
[root@master ~]# 

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

b 分支命令除了可以向后跳转,还可以向前跳转,例如:

[root@master ~]# echo "This, is, a, test, to, remove, commas." | sed -n '{
> :start
> s/,//1p
> /,/b start
> }'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.

在这个例子中,当缓冲区中的行内容中有逗号时,脚本命令就会一直循环执行,每次迭代都会删除文本中的第一个逗号,并打印字符串,直至内容中没有逗号。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值