sed模式空间命令

本文详细介绍了sed命令中的模式空间和保持空间的概念及其作用,阐述了sed处理文件的流程。重点讲解了如何利用n、N、h、H、g、G、x命令在模式空间和保持空间间操作数据,以及如何处理多行模式空间问题。此外,还探讨了sed中的高级控制命令,如b和t,用于改变脚本执行流程。通过实例展示了sed在文本处理中的强大功能。
摘要由CSDN通过智能技术生成

一、 模式空间和保持空间的概念

sed 有两个内置的存储空间:

名称概念
模式空间(pattern space)模式空间用于 sed 执行的正常流程中。该空间 sed 内置的一个缓冲区,用来存放、修改从输入文件读取的内容。
保持空间 (hold space)保持空间是另外一个缓冲区,用来存放临时数据。Sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。

二、sed工具的执行流程

sed编辑器逐行处理文件,并将输出结果打印到屏幕上。sed命令将当前处理的行读入模式空间(pattern space)进行处理,sed在该行上执行完所有命令后就将处理好的行打印到屏幕上(除非之前的命令删除了该行),sed处理完一行就将其从模式空间中删除,然后将下一行读入模式空间,进行处理、显示。处理完文件的最后一行,sed便结束运行。sed在临时缓冲区(模式空间)对文件进行处理,所以不会修改原文件,除非显示指明 -i 选项。
在这里插入图片描述
与模式空间和暂存空间(hold space)相关的命令:

n 输出模式空间行,读取下一行替换当前模式空间的行,执行下一条处理命令而非第一条命令。
N 读入下一行,追加到模式空间行后面,此时模式空间有两行。
h 把模式空间里的行拷贝到暂存空间。
H 把模式空间里的行追加到暂存空间。
g 用暂存空间的内容替换模式空间的行。
G 把暂存空间的内容追加到模式空间的行后。
x 将暂存空间的内容于模式空间里的当前行互换。
! 对所选行以外的所有行应用命令。
注意:暂存空间里默认存储一个空行。

使用场景

处理多行模式空间的问题( N、D、 P )

采用保持空间来保存模式空间的内容并使它可用于后续的命令 ( H、h、G、g、x)

编写使用分支和条件指令的脚本来更改控制流( :、b、t )

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

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

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

[root@localhost ~]# cat test.txt 
Ji feng jian hao
Ya suo
Wu ji jian sheng
Yi
Ba tian jian mo
Ya tuo ke si



[root@localhost ~]# 
[root@localhost ~]# sed '/Ji/{N;s/\n/ /}' test.txt 
Ji feng jian hao Ya suo
Wu ji jian sheng
Yi
Ba tian jian mo
Ya tuo ke si

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

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

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

[root@localhost ~]# sed '/^$/{N;/^\n$/d}' lol.txt 
Yasuo 1

Yatuokesi 2
Feiaona 3

Feizi 4
Liqing 5
[root@localhost ~]# 

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

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

Yatuokesi 2

Feiaona 3

Feizi 4

Liqing 5

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

三、保持空间

sed 中除了模式空间,还另外还支持保持空间(Hold Space)
利用此空间,可以将模式空间中的数据,临时保存至保持空间
从而后续接着处理,实现更为强大的功能
模式空间可以理解为前台,保持空间可以理解为后台
保持空间是另外一个缓冲区,用来存放临时数据。Sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。我们已经讨论过,每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容则保持不变,不会在循环中被删除

保持空间的用途: 当改变模式空间中的原始文件时,用于保留当前输入行的副本

编写功能
h或H将模式空间的内容复制或追加到保持空间
g或G将保持空间的内容复制或追加到模式空间
x交换保持空间和模式空间的内容

原理
在这里插入图片描述
实例:

[root@localhost ~]# cat tests    //文本内容如下
2
3
22
33
222
333
2222
3333
[root@localhost ~]# 

[root@localhost ~]# sed '/2/{h;d};/3/{G}' tests
3
2
33
22
333
222
3333
2222
[root@localhost ~]# 

复制模式空间内容到保持空间,在将匹配到模式空间的内容追加到保持空间中。然后将保持空间的内容覆盖到模式空间中输出,例子如下:

[root@localhost ~]# cat tests 
2
3
22
33
222
333
2222
3333
[root@localhost ~]# 

[root@localhost ~]# sed '/2/{h};/3/{H;g}' tests
2
2
3
22
22
33
222
222
333
2222
2222
3333
[root@localhost ~]#

匹配is和statenent中间内容将其复制到保持空间中,然后输出中间匹配的内容

[root@localhost ~]# cat tests 
This is Shen statement long
This is Jerry statement long
[root@localhost ~]# 

写一个测试文件

[root@localhost ~]# cat haha 
/is .* statement/{
h
s/.*is (.*) statement.*/\1/
}

[root@localhost ~]# 

结果

[root@localhost ~]# sed -rf haha tests
Shen
Jerry

替换命令行中提取语句的名字,并用它代替整行,转换命令将小写字母转换为大写字母。

[root@localhost ~]# cat tests 
This is Shen statement long
This is Jerry statement long
[root@localhost ~]# 
[root@localhost ~]# cat haha 
/is .* statement/{
h
s/.*is (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/(.*)\n(.*is ).*( statement.*)/\2\1\3/
}

[root@localhost ~]# 

结果

[root@localhost ~]# sed -rf haha tests
This is SHEN statement long
This is JERRY statement long
[root@localhost ~]# 

四、高级的控制命令

之前我们学习了一些改变sed的正常流控制的实例。接下来我们要用到的是用于控制执行脚本的那一部分以及何时执行的命令,分支(b)和测试(t)。这两条命令将脚本中的控制转移到包含特殊标签的行。如果没有指定标签,则将控制转移到脚本的结尾处。分支命令用于无条件转移,测式命令用于有条件转移,它们只有当替换命令改变当前行时才会执行。

标签:任意的字符组合且长度不大于7,它本身占据一行且以冒号开头

:mylabel

冒号和标签之间不能有空格,标签后的空格会被当做标签的一部分

标签和命令之间允许有空格

分支(b)

b ( branch),在脚本中将控制权转到另一行,通过它你可以跳到你想去的地方,它可以将一组命令当做一个过程来执行且这个过程在脚本中可以重复执行,只要条件满足。

语法:[address]b [label]
address:决定在哪行或哪些行执行分支命令
label:参数定义于何处分支

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

[root@localhost ~]# cat tests 
This is the sss

This is the sss

This is the hhh

[root@localhost ~]# 
[root@localhost ~]# sed '{
2,3b    //这里的意思是跳过2和3这两行
s/This is /Is this /
s/sss/niubi/
}' tests
Is this the niubi

This is the sss

Is this the ggg

[root@localhost ~]# 

在这里因为 b 命令未指定 label 参数,因此数据流中的第2行和第3行并没有执行那两个替换命令

测试(t)

类似于 b 分支命令,t 命令也可以用来改变 sed 脚本的执行流程。t 测试命令会根据 s 替换命令的结果,如果匹配并替换成功,则脚本的执行会跳转到指定的标签;反之,t 命令无效

语法:[address]t [label]

在没有指定标签的情况下,如果 s 命令替换成功,sed 会跳转到脚本的结尾(相当于不执行任何脚本命令)

例子:

[root@localhost ~]# cat tests 
This is the red line
This is the sleep data line
This os a butst data line
This is the last line
[root@localhost ~]#
[root@localhost ~]# sed '{
> s/sleep/matched/
> t
> s/This is the/NO match on/
> }' tests
NO match on red line
This is the matched data line
This os a butst data line
NO match on last line
[root@localhost ~]# 

在这里第一个替换命令会查找模式文本 first,如果匹配并替换成功,命令会直接跳过后面的替换命令;反之,如果第一个替换命令未能匹配成功,第二个替换命令就会被执行,执行如下:

[root@localhost ~]# echo "This, is, a, one, two, tree" | sed -n '{
> :start
> s/,//1p
> t start
> }'
This is, a, one, two, tree
This is a, one, two, tree
This is a one, two, tree
This is a one two, tree
This is a one two tree
[root@localhost ~]# 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值