高级sed命令

1. sed高级命令介绍

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

脚本由于各种原因中断或暂停了正常的控制流。它们也许想阻止脚本中的命令被执行,某些特定的情况除外,或者阻止模式空间的内容被清除。更改控制流会使脚本更加难以阅读和理解。事实上,写脚本比读脚本更容易。当你编写很难的脚本时,测式它来看看命令如何工作对你会有好处。

sed在正常情况下,将处理的行读入模式空间(pattern space)脚本中的“sed-command(sed命令)”就一条接着一条进行处理,直到脚本执行完毕。然后该行被输出,模式(pattern space)被清空;接着,在重复执行刚才的动作,文件中的新的一行被读入,直到文件处理完毕。(就是追加下一行)

//写一个测试文件,以下实验皆基于此测试文件的内容
[root@localhost ~]# cat > abc <<EOF
> The world is spl
> endid and grand.Welco
>  me home
> EOF
[root@localhost ~]# cat abc 
The world is spl
endid and grand.Welco
 me home
 

2. N命令使用

N追加,将下一行添加到pattern space中。将当前读入行和用N命令添加的下一行看成“一行”


//把换行符替换成空,\n表示换行符
[root@localhost ~]# sed '/spl/N;s/\n//' abc
The world is splendid and grand.Welco
 me home
 
//把e替换成b
[root@localhost ~]# sed '/spl/N;s/\ne/b/' abc
The world is splbndid and grand.Welco
 me home
 
//写一个文件,进行处理
[root@localhost ~]# cat test 
/spl/{
N;s/\n//}
[root@localhost ~]# sed -f test abc
The world is splendid and grand.Welco
 me home
 
//写一个文件处理多行,对空格进行处理
[root@localhost ~]# cat test 
/spl/{
N;s/\n//
N;s/\n //
}
[root@localhost ~]# sed -f test abc
The world is splendid and grand.Welcome home

//在命令行输入
[root@localhost ~]# sed '/spl/{N;s/\n//;N;s/\n //}' abc
The world is splendid and grand.Welcome home

3. D命令使用

sed命令之D命令:
如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本, 并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间 不包含换行符,则会像发出d命令那样启动正常的新循环。(删除第一行,但第二行保留)


//匹配spl然后删除
[root@localhost ~]# sed '/spl/d' abc
endid and grand.Welco
 me home
 
//多行模式空间进行删除
[root@localhost ~]# sed '/spl/{N;D}' abc
endid and grand.Welco
 me home
 
//执行两个任务,删除两行
[root@localhost ~]# sed '/spl/{N;D};/Welco/{N;D}' abc
 me home

4.P多行打印命令

同d 和 D 之间的区别一样,P(大写)命令和单行打印命令 p(小写)不同,对于具有多行数据的缓冲区来说,它只会打印缓冲区中的第一行,也就是首个换行符之前的所有内容。

//text文件中内容
[root@localhost ~]# cat text 
Here are example of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System

使用P命令

[root@localhost ~]# cat aaa
/UNIX$/{
N
/\nSystem/{
s// Operating &/
P
D
}
}
[root@localhost ~]# sed -f aaa text 
Here are example of the UNIX Operating 
System. Where UNIX Operating 
System appears, it should be the UNIX
Operating System

5. sed保持空间

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

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

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

[root@localhost ~]# cat my.txt 
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed -n '/first/ {h ; p ; n ; p ; g ; p }' my.txt 
This is the first data line.
This is the second data line.
This is the first data line.

运行过程:
sed脚本命令用正则表达式过滤出含有单词first的行;
当含有单词 first 的行出现时,h 命令将该行放到保持空间;
p 命令打印模式空间也就是第一个数据行的内容;
n 命令提取数据流中的下一行(This is the second data line),并将它放到模式空间;
p 命令打印模式空间的内容,现在是第二个数据行;
g 命令将保持空间的内容(This is the first data line)放回模式空间,替换当前文本;
p 命令打印模式空间的当前内容,现在变回第一个数据行了。

[root@my ~]# cat list       
find the match statement  uagidvbiyhavwi
abcde the tom statement  uagidvbiyhavwi
abcde the jerry statement  uagidvbiyhavwi
[root@my ~]# cat sedscript                                            
/the .* statement/{		        
h                                
s/.*the (.*) statement.*/\1/ }     
[root@my ~]# sed -rf sedscript list       
Match
tom
jerry
#基于以上,再将3行内容换成大写
[root@my ~]# cat sedscript 
/the .* statement/{
h
s/.*the (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ 
}
[root@my ~]# sed -rf sedscript list
MATCH
TOM
JERRY
#再基于以上,将保持空间的内容全部复制到模式空间,调换位置即可
root@my ~]# cat sedscript 
/the .* statement/{
h
s/.*the (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/(.*)\n(.*the) .*(statement)/\2 \1 \3/                                       
}
[root@my ~]# sed -rf sedscript list
find the MATCH statement  uagidvbiyhavwi
abcde the TOM statement  uagidvbiyhavwi
abcde the JERRY statement  uagidvbiyhavwi       
#以上均是呈现的模式空间的效果
[root@my ~]# sed -i -r -f sedscript list
[root@my ~]# cat list
find the MATCH statement  uagidvbiyhavwi
abcde the TOM statement  uagidvbiyhavwi
abcde the JERRY statement  uagidvbiyhavwi

6.b分支命令

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

b 分支命令基本格式为:

[address]b [label]

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

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

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值