进阶sed

1 多行命令

N:将数据流中的下一行加进来创建一个多行组来处理

D:删除多行组中的一行

P:打印多行组中的一行

next命令

删掉两个空行

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data3
header line

data line

last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '/^$/d' data3 
header line
data line
last line
复制代码

如果需要删除第一个空行,但是没有任何能够标识空行的文本。解决办法是用n命令,查找到header行,n命令会让sed编辑器移动到文本的下一行,也就是空行

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '/header/{n;d}' data3
header line
data line

last line

合并文本行

多行版本的next命令(用大写的N)会将下一行添加到模式空间中已有的文本后

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data4 
header line
first data line
second data line
last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '/first/{N;s/\n/ /}' data4 
header line
first data line second data line
last line
复制代码

查找分散在两行中的文本短语,N比较实用,这边用通配符(.)来匹配空格或者换行符

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed 'N;s/system administrator/desktop user/' data5 
on tuesday,the linux system
administrator's group meeting well be held
all system administrator show attend.
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed 'N;s/system.administrator/desktop user/' data5 
on tuesday,the linux desktop user's group meeting well be held
all system administrator show attend.
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data5
on tuesday,the linux system
administrator's group meeting well be held
all system administrator show attend.
复制代码

但是仍有小问题,这个脚本总是在执行sed编辑命令前将下一行文本读入到模式空间,当它执行到最后一行的时候,就没有下一行可堵了,所以N命令会

叫sed编辑器停止,由于system administrator出现在了最后一行,可以这么解决:

将单行命令放到N命令前面,多行命令放到N命令后面

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed 's/system administrator/desktop user/;N;s/system.administrator/desktop\n user/' data5
on tuesday,the linux desktop
 user's group meeting well be held
all desktop user show attend.

多行删除命令

d单行删除

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed 'N;/system\nadministrator/d' data5
all system administrator show attend.

D多行删除

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed 'N;/system\nadministrator/D' data5
administrator's group meeting well be held
all system administrator show attend.

删除数据流中出现在第一行前的空白行

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '/^$/{N ; /header/D}' data3
header line

data line

last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data3 

header line

data line

last line
复制代码

多行打印命令

-n阻止脚本输出,p和P大同小异,P只打印多行模式空间的第一行

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed -n 'N;  /system\nadministrator/p' data5
on tuesday,the linux system
administrator's group meeting well be held
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed -n 'N;  /system\nadministrator/P' data5
on tuesday,the linux system

保持空间

h  将模式空间复制到保持空间

H  将模式空间附加到保持空间

g  将保持空间复制到模式空间

G  将保持空间附加到模式空间

x  交换模式空间和保持空间内容

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data4 
header line
first data line
second data line
last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed -n '/first/{h;p;n;p;g;p}' data4
first data line
second data line
first data line
复制代码

分析以上代码

1、sed脚本在地址中用正则表达式过滤出含有first的行

2、当含有first的行出现时,h将该行放入保持空间

3、p命令打印模式空间的内容,第一个数据行内容

4、n命令提取数据流下一行,并放到模式空间

5、p打印模式空间内容,现在是第二个数据行

6、g将保持空间的内容放回到模式空间,替换当前内容

7、p打印模式空间的内容

 

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data4 
header line
first data line
second data line
last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed -n '{1!G;h;$p}' data4 
last line
second data line
first data line
header line
复制代码

分支

分支(branch)命令b格式如下,允许支队数据流中的特定行执行一组命令

[address]b [label]

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '{2,3b ; s/line/lines/}' data4 
header lines
first data line
second data line
last lines
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '{ 2,3b ;s/this is/is this/ ; s/data line/date lines/}' data4 
is this header date lines
this is first data line
this is second data line
is this last date lines

 

分支命令可以定义一个要跳转到的标签,标签以冒号开始,最多可以是7个字符长度

:label2

要指定标签,加到b命令后面即可,使用标签允许跳过地址匹配出的命令,但仍然执行脚本中其他命令

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# cat data4
this is header line
this is first data line
this is second data line
this is last line
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed '{/first/b app1 ; s/this is/no jump on/ ;:app1 ;s/this is/jump here on/}' data4 
no jump on header line
jump here on first data line
no jump on second data line
no jump on last line
复制代码

 跳转命令指定如果文本行中出现了first,程序应该跳到标签为app1的脚本行。如果分支命令的模式没有匹配,sed编辑器会继续执行脚本命令,包括分支标签后的命令,

因此,所有的替换命令都会在不匹配分支模式的行上执行

如果某行匹配了分支模式,sed编辑器就会跳到带有分支标签的那行,因此,只有最后一个替换命令会执行。

这个例子演示了跳转到sed脚本后面的标签上。也可以跳转到脚本中靠前的标签上,这样就达到了循环的效果

复制代码
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# echo "this, is, a, test, do, remove, commas."|sed -n '{
:start
s/,//p 
/,/b start
}'
this is, a, test, do, remove, commas.
this is a, test, do, remove, commas.
this is a test, do, remove, commas.
this is a test do, remove, commas.
this is a test do remove, commas.
this is a test do remove commas.
复制代码

脚本每次迭代都会删除第一个逗号,并打印字符串。只会在行中有逗号的时候进行跳转,最后一个逗号被删除后,分支命令不再会执行。

测试

测试命令使用与分支命令相同的格式

[adress]t [label]

跟分支命令一样,在没有指定标签的情况下,如果测试成功,sed会跳到脚本的结尾

测试命令提供了对数据流中文本执行基本的if-then语句的一个低成本办法。

举个例子,如果已经做了一个替换,不需要做另一个替换,就可以用测试命令

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# sed  '{s/first/matched/ ;t ;s/this is/no match/}' data4 
no match header data line
this is matched data line
no match second data line
no match last data line

第一个命令会查找模式文本first,如果匹配了行中模式,就会替换文本,而测试命令会跳过后面的替换命令来替换该行,去替换其他行中匹配的行。如果未匹配,则后面的替换命令会将该行也替换

有了测试命令,就能结束之前用分支命令形成循环

复制代码
:start
s/,//p
t start
}'
this is, a, test, do, remove, commas.
this is a, test, do, remove, commas.
this is a test, do, remove, commas.
this is a test do, remove, commas.
this is a test do remove, commas.
this is a test do remove commas.
复制代码

模式替换

&符号

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# echo "the cat sleeps in the hat" | sed  's/.at/"&"/g'
the "cat" sleeps in the "hat"

&符号会提取匹配替换命令中指定模式的整个字符串,如何提取部分:

sed编辑器用圆括号来定义替换模式中的子模式,可以在替代模式中使用特殊字符来引用每个子模式。替代字符由反斜线和数字组成。数字表明子模式的位置。

sed编辑器会给第一个子模式分配字符\1,给第二个字模式分配字符\2,以此类推

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# echo "the system administrator manual"|sed 's/\(system\) administrator/\1 user/'
the system user manual
[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# echo "that furry cat is pretty"|sed 's/furry \(.cat\)/\1/'
that furry cat is pretty

在大数字中插入逗号

[root@iZbp11f8g5h7oozejqy6k6Z test5.9]# echo "1234567"|sed '{:start ;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;t start}'
1,234,567

将匹配模式分为

.*[0-9]

[0-9]{3}

 

posted @   Tatataaa  阅读(32)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示