sed高级用法,处理了多行模式空间(N、D、P)

sed高级用法,处理了多行模式空间(N、D、P)

sed高级用法

###可以把 sed高级命令分成3个组:
1.处理了多行模式空间(N、D、P)。
2.采用保持空间来保存模式空间的内容并使它可用于后续的命令(H、h、G、g、x) 。
3.编写使用分支和条件指令的脚本来更改控制流(:、b、t) 。

改变执行或控制的流程顺序,通常一行被读入模式空间并且用脚本中的每个命令(一个接一个地)应用于那一行。当达到脚本的底部时,输出这一行并且清空模式空间。然后新行被读入模式空间,并且控制被转移回脚本的顶端。这是sed脚本中正常的控制流。

1、多行模式空间

模式匹配是面向行的,像grep这样的程序尝试在单个输入行上匹配一个模式。这就使它很难匹配一个在一行的结尾处开始。并在下一行的开始处结束的短语。其他一些模式只有当在多行上重复时才有意义。

sed能查看模式空间的多个行。这就是允许匹配模式扩展到多行上。我们来看一下创建多行模式空间并处理它的内容的命令。这里的3个多行命令(N、D、P)对应于小写字母的基本命令(n、d、p)。例如,删除命令(D)是删除命令(d)的多行形式。区别是:d删除单行模式空间的内容,D只删除多行模式空间的第一行。

Next 命令(N):将数据流中的下一行追加到模式空间,形成多行模式空间
Delete(D):删除多行组中的一行。
Print(P):打印多行组中的一行。

2、 追加下一行

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

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

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

#匹配到此行,把换行替换成空行
[root@kh2 ~]# cat test 
xion
gke shi wo  er zi zu
 i xi huan fang pi
[root@localhost opt]# sed '/xion/N;s/\n//;' test 
xiongke shi wo sha er zi zu
 i xi huan fang pi
[root@localhost opt]# 

#多行匹配,换成空行

[root@localhost opt]#  sed  '/xion/{N;s/\n//;N;s/\n //};' test 
xiongke shi wo sha er zi zui xi huan fang pi
[root@localhost opt]# 

##也可以把执行命令放入一个文件
[root@localhost opt]# cat sedexport 
/xion/{
N;s/\n//
N;s/\n //
}
[root@localhost opt]# 

[root@localhost opt]# sed -f sedexport test 
xiongke shi wo sha er zi zui xi huan fang pi

3、D 多行删除命令

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

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

##编写一个txt文件,删除掉里面的空行
[root@kh2 ~]# cat test 
xiong da jiao xioym .

xiong er jiao xiongke .


guang tou qiang jiao ff .



ji ji jiao shunzi .




jjyyyqqccabc
#删除掉文件里面的空行
[root@kh2 ~]# sed '/^$/{N;/^\n$/d}' test	#小写d只会删除偶数的空行
xiong da jiao xioym .						 奇数会保留一行

xiong er jiao xiongke .
guang tou qiang jiao ff .

ji ji jiao shunzi .
jjyyyqqccabc

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

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

#使用大D(Delete)则命令
[root@kh2 ~]# sed '/^$/{N;/^\n$/D}' test 	#无论奇数还是偶数都会保留一行
xiong da jiao xioym .

xiong er jiao xiongke .

guang tou qiang jiao ff .

ji ji jiao shunzi .

jjyyyqqccabc

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

4、多行打印(Print)

多行打印(Print)命令与小写字母的print命令稍有不同。该命令输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出(-n选项或#n 抑制这个默认的动作)。因此,当默认的输出被抑制或者脚本中的控制流更改,以至不能到达脚本的底部时,需要使用打印命令(P或p) .

Print命令经常出现在Next命令之后和Delete命令之前。这3个命令能建立一个输入/输出循环,用来维护两行的模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。
Next命令将一个新的输入行追加到模式空间的当前行。在替换命令应用于多行模式空间之后,模式空间的第一部分被Print命令输出,然后被Delete命令删除。这意味着当前被输出并且新的行成为当前行。Delete命令阻止脚本到达底部,这将输出两行并清除模式空间的内容。Delete命令让我们保护了模式空间的第二部分,并将控制转移动脚本的顶端,在顶端所有的编辑命令都可以被应用于一行。这些命令中有一个是Next命令,它将另一个新行读入模式空间。

## 编写一个测试文件
[root@localhost opt]# cat test 
Here are examples of the UNIX
System. Where UNIX
System appears,it should be the UNIX
Operating System.

##执行命令
[root@kh2 ~]# sed '/UNIX/{N;/\nSystem/{s// xkez &/;P;D}}' test 
Here are examples of the UNIX xkez 
System. Where UNIX xkez 
System appears,it should be the UNIX
Operating System.

创建多行模式空间以匹配第一行结尾处的“UNIX”和第二行开始处的“System”。如果发现“UNIX System”跨越两行,那么我们将它变成“UNIX xkez”。建立这个循环以返回到脚本的顶端,并寻找第二行结尾处的‘UNIX’.

5、保持空间

模式空间是容纳当前输入行的缓冲区。还有一个称为保持空间(hold space)的顶留(set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持空间用于临时存储。单独的命令不能寻址保持空间或者更改它的内容。
保持空间最常的用途是,当改变模式空间中的原始内容时,用于保留当前输入行的副本。影响模式空间的命令有:
模式空间是容纳当前输入行的缓冲区。还有一个称为保持空间(hold space)的顶留(set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持空间用于临时存储。单独的命令不能寻址保持空间或者更改它的内容。
保持空间最常的用途是,当改变模式空间中的原始内容时,用于保留当前输入行的副本。影响模式空间的命令有:
命令 缩写 功能
Hold h或H 将模式空间的内容复制或追加到保持空间
Get g 或G 将保持空间的内容复制或追加到模式空间
Exchange x 交换保持空间和模式空间的内容

这些命令中的每一条都可以利用一个地址来指定一行或行范围。Hole(h,H)命令将数据移至保持空间、而get (g.G)命令将保持空间的数据移回到模式空间。同一命令的小写字母和大写字母之间的差别是,小字字母命令改写目的缓存区的内容,而大写字母命令追加缓存区的现有内容。

其中:

Hold命令用模式空间的内容取代保持空间的内容。get命令用保持空间的内容取代模式空间的内容。
Hole命令在保持空间的内容之后放置一个换行符,且后面跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。Get命令模式空间的内容之后放置一个换行符,且后面跟随保持空间的内容。
交换命令交换两个缓存区的内容,对两个缓存区没有副作用。

我们使用较通俗的示例来解释在保持空间放入行,并在稍后检索它们的情况。我们将编写一个脚本来反转部分行。我们将使用一个数字列表作为样本文件,这里的目的是颠倒以1开始的行和以2开始的行的顺序。下面展示了如何使用保持空间:

## 编写一个测试文件
[root@kh2 ~]# cat test 
1
2
11
22
111
222
##我们将第一行复制到保持空间(它一直在那),这时清除模式空间。然后sed将第二行读入模式空间,并且将保持空间的行追加到模式空间的结尾。请看下面的脚本:
[root@localhost opt]# cat sedexport 
/1/{
h
d
}
/2/{
G
}
## 匹配“1”的任何行都被复制到保持空间并且从模式空间删除。控制转移到脚本的顶端并且不打印那一行。当读取下一行时,它匹配模式“2”且将已经复制到保持空间的行追加到模式空间之后。然后两行都被打印出来。换句话说,我们保存这两行中的第一行并且直到匹配第二行时才输出它
[root@kh2 ~]# sed '/1/{h;d};/2/{G}' test 
2
1
22
11
222
111

## 先匹配1到模式空间,复制到保持空间;然后匹配2,模式空间里就有1和2,做追加到保持空间,保持空间里就有112了,然后又替换到模式空间,模式空间里就有了1 1 2
[root@localhost opt]# sed '/1/{h};/2/{H;g}' test 
1
1
2
11
11
22
111
111
222
[root@localhost opt]# 

大写转换

上一章我们介绍了转换命令(y),并且描述了在一行上如何将小写字母转换为大写字母。因为y命令作用于模式空间的所有内容,所以对行的一部分进行逐字转换有点繁琐。尽管这有点令人费解,但也是可能的,正如下面的示例所演示那样。

当编写程序设计指南时,我们发现语句的名字输入不一致,它们应该都为大写字母,但是有一些是小写字母另-些的首字母却是大写的。虽然任务很简单,就是将语句的名字改成大写,但是这里有将近100条语句。编写如何之多的显式替换似乎是作件冗长乏味的工作。

转换命令可以进行小写字母到大写字母的转换,但它将转换应用于整个行。使用保持空间可以实现以上任务,因为可以用保持空间来存储输入行的备份而将语句名独立出来,并在模式空间进行转换。先来看看脚本:

#要求把the和statement中间的哪个单词修改为大写
[root@kh2 ~]# cat test 
find the Match statement
Consult the Get statement.
Using the Read statement to retrieve data

[root@kh2 ~]# sed -r '/the .* statement/{h;s/.* the (.*) statement.*/\1/;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/;G;s/(.*)\n(.* the ).*( statement.*)/\2\1\3/g}' test 
find the MATCH statement
Consult the GET statement.
Using the READ statement to retrieve data

6、sed改变指定流程

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

b 分支命令基本格式为:
[address]b [label]

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

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

源文件:

[root@localhost ~]# cat test 
This is the computer line.
This is the name data line.
This is the classroom data line.
This is the bycome line.

##执行以下命令
[root@localhost ~]# sed '{2,3b;s/the/The/;s/line/.test?/}' test
This is The computer .test?.
This is the name data line.
This is the classroom data line.
This is The bycome .test?.

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

同时也可以在sed命令中添加标签实现控制如下

##编写一个测试文件
[root@localhost ~]# cat test
This is the computer line.
This is the name data line.
This is the classroom data line.
This is the computer line.

##执行以下命令
[root@localhost ~]# cat sed.txt 
:head
/the/{
/classroom/b head
s/computer/abc/
}
##结果
[root@localhost ~]# sed -f sed.txt test
This is the abc line.
This is the name data line.

执行后发现,命令还未执行完也不退出,一直处于第二行,这是为什么呢?

执行流程
首先 /the/ ##匹配含the字符的行

匹配到the时 继续执行 /classroom/b head ##再次匹配含有the当前行中,是否有classroom,若有则会回到 head,若没有则执行 s/computer/abc/ ## 将匹配到的computer替换为abc

## 命令执行流程
[root@localhost ~]# cat txt
This is the computer line.       ## 匹配the成功,替换computer成功
This is the name data line.      ## 匹配the成功,继续向下执行,匹配不到  
                                 ## classroom,匹配不到computer,不替换   
This is the classroom data line.    ## 匹配 the 成功,继续执行,匹配到classroom ,返回head ,进入死循环
This is the computer line.

x 交换保持空间或模式空间的内容

[root@localhost ~]# cat txt
This is the computer line.
This is the name data line.
This is the classroom data line.
This is the become line.

## 执行以下命令
[root@localhost ~]# sed -n '/name/ {h;x;p}' com.txt 
This is the name data line.


## 若不加-n则是
[root@localhost ~]# sed  '/name/ {h;x;p}' com.txt 
This is the computer line.
This is the name data line.
This is the name data line.
This is the classroom data line.
This is the become line.

h 将匹配到的name 行 ,添加至保持空间
x 将保持空间的内容和模式空间互换
p 打印
原文链接:https://blog.csdn.net/m0_56305656/article/details/120358852

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值