21. sed进阶

21. sed进阶

21.1 多行命令

有时需要对跨多行的数据执行特定操作。sed编辑器包含了三个可用来处理多行文本的特殊命令。
N:将数据流中的下一行加进来创建一个多行组(multiline group)来处理。
D:删除多行组中的一行。
P:打印多行组中的一行。

21.1.1 next命令

1.单行的next命令
使用n移动到文本的下一行,并实现对应的删除

$ cat data1.txt 
This is the header line. 
 
This is a data line. 
 
This is the last line.
$
$ sed '/header/{n ; d}' data1.txt
This is the header line. 
This is a data line. 
 
This is the last line.

2.合并文本行
N会将下一行与指定文本行进行合并,当成一行。例如下面首先找到first所在的行,然后

$ 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. 
$  
$ sed '/first/{ N ; s/\n/ / }' data2.txt 
This is the header line. 
This is the first data line. This is the second data line. 
This is the last line.

实现文本替换,首先使用N将首行和下一行合并,然后使用.通配符匹配一个字符,这里是\n,这样就匹配了第一行,使用Desktop User替换之后得到最后的结果。

$ cat data3.txt 
On Tuesday, the Linux System 
Administrator's group meeting will be held. 
All System Administrators should attend. 
Thank you for your attendance.

$ sed 'N ; s/System.Administrator/Desktop User/' data3.txt 
On Tuesday, the Linux Desktop User's group meeting will be held. 
All Desktop Users should attend. 
Thank you for your attendance.

上述存在两个问题
上面的代码破坏了原本的文本结构,如果要维持的话就要使用下面的命令:

sed 'N 
> s/System\nAdministrator/Desktop\nUser/ 
> s/System Administrator/Desktop User/ 
> ' data4.txt

如果System Administrator文本出现在了数据流中的最后一行,会导致无法实现下一行的匹配:

$ sed ' 
> s/System Administrator/Desktop User/ 
> N 
> s/System\nAdministrator/Desktop\nUser/ 
> ' data4.txt 
On Tuesday, the Linux Desktop 
User's group meeting will be held. 
All Desktop Users should attend.
21.1.2 多行删除命令

单行删除命令d,sed编辑器用它来删除模式空间中的当前行,因此如果使用N匹配了连续的两行,就会发生删除两行。

$ cat data4.txt 
On Tuesday, the Linux System 
Administrator's group meeting will be held. 
All System Administrators should attend.

$ sed 'N ; /System\nAdministrator/d' data4.txt 
All System Administrators should attend.

多行删除命令D,删除模式空间中的第一行到换行符为止的所有字符

$ sed 'N ; /System\nAdministrator/D' data4.txt 
Administrator's group meeting will be held. 
All System Administrators should attend.
21.1.3 多行打印命令

多行打印命令(P)沿用了同样的方法。它只打印多行模式空间中的第一行,这包括模式空间中直到换行符为止的所有字符。

21.2 保持空间

模式空间(pattern space)是一块活跃的缓冲区,在sed编辑器执行命令时它会保存待检查的文本。

sed编辑器有另一块称作保持空间(hold space)的缓冲区域。
sed保持空间
运用上面的例子,

$ 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. 
$  
$ sed -n '/first/ {h ; p ; n ; p ; g ; p }' data2.txt
This is the first data line. 
This is the second data line. 
This is the first data line.

21.3 排除命令

!是让原本的命令起到反作用,例如:

$ sed -n '/header/!p' data2.txt
This is the first data line. 
This is the second data line. 
This is the last line.

逆序打印所有的行,需要根据模式空间和保持空间两个空间的特性,例如:
逆序打印行
实现上述流程图的命令格式为$ sed -n '{1!G ; h ; $p } ' filename

21.4 改变流

21.4.1 分支

使用b指令进行跳转。

任务一:循环替换下面的,例如echo打印一段话,然后使用sed -n指令,用:start声明start的地址,然后使用s/,//使用无间隔替换逗号,最后使用b跳转到start的位置。

echo "This, is, a, test, to, remove, commas." | sed -n '{
:start
s/,//1p
b start
}'

上述代码会无限循环,为了防止这个问题,可以为分支命令指定一个地址模式查找,即将b start替换为/,/b start

21.4.2 测试

根据替换命令的结果跳转到某个标签,如果替换命令没能匹配指定的模式,测试命令不会跳转。

$ echo "This, is, a, test, to, remove, commas. " | sed -n '{ 
> :start 
> s/,//1p 
> t 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. 
$

21.5 模式替代

21.5.1 &符号

&符号可以用来代表替换命令中的匹配的模式。不管模式匹
配的是什么样的文本,你都可以在替代模式中使用&符号来使用这段文本。

$ echo "The cat sleeps in his hat." | sed 's/.at/"&"/g' 
The "cat" sleeps in his "hat".
21.5.2 替代单独的单词

如果只需要匹配模式中的某个字符串,需要指定子模式使用\( \),第一个子模式为\1,第二个子模式为\2
1.按照子模式进行替换

$ echo "That furry cat is pretty" | sed 's/furry \(.at\)/\1/' 
That cat is pretty

上面的代码本来是要匹配furry cat的,使用的是子模式进行替换,可以看见\1cat替换了原本的字符串。

2.在子模式之间添加一些符号:

$ echo "1234567" | sed '{ 
> :start 
> s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/ 
> t start 
> }' 
1,234,567 
$

21.6 在脚本中使用sed

21.6.1 使用包装脚本

在reverse.sh的脚本中编写对应的指令。

$ cat reverse.sh 
#!/bin/bash 
# Shell wrapper for sed editor script. 
#               to reverse text file lines. 
sed -n '{ 1!G ; h ; $p }' $1

使用shell参数传递对应的指令

$ ./reverse.sh data2.txt 
This is the last line. 
This is the second data line. 
This is the first data line. 
This is the header line.
21.6.2 重定向sed输出

可以在脚本中用$()将sed编辑器命令的输出重定向到一个变量中,以备后用。

21.7 创建sed实用工具

21.7.1 加倍行间距

G是将保持空间附加到模式空间,启动sed编辑器时,保持空间只有一个空行。

$ sed 'G' data2.txt 
This is the header line. 
 
This is the first data line. 
 
This is the second data line. 
 
This is the last line.

但是上面的代码对最后一行也添加了空行,可以实现对最后一行的修正。

$ sed '$!G' data2.txt 
This is the header line. 
 
This is the first data line. 
 
This is the second data line. 
 
This is the last line.
21.7.2 对可能含有空白行的文件加倍行间距
$ cat data6.txt 
This is line one. 
This is line two. 
 
This is line three. 
This is line four.

$ sed '/^$/d ; $!G' data6.txt 
This is line one. 
 
This is line two. 
 
This is line three. 
 
This is line four.
21.7.3 给文件中的行编号

使用$!=防止给最后一行编号,然后使用N连接两行并将换行替换为空格。

$ sed '$!=' data2.txt | sed 'N; s/\n/ /' 
1 This is the header line. 
2 This is the first data line. 
3 This is the second data line. 
4 This is the last line.
21.7.4 打印末尾行

打印最后一行,得到打印结果

$ sed -n '$p' data2.txt 
This is the last line.

假如需要打印最后10行,可以使用滑动窗口解决这个问题,首先规定到了最后一行的时候直接退出$q,然后使用N实现将

$ cat data7.txt 
This is line 1. 
This is line 2. 
This is line 3. 
This is line 4. 
This is line 5. 
This is line 6. 
This is line 7. 
This is line 8. 
This is line 9. 
This is line 10. 
This is line 11. 
This is line 12. 
This is line 13. 
This is line 14. 
This is line 15. 
$ 
$ sed '{ 
> :start 
> $q ; N ; 11,$D 
> b start 
> }' data7.txt 

This is line 6. 
This is line 7. 
This is line 8. 
This is line 9. 
This is line 10. 
This is line 11. 
This is line 12. 
This is line 13. 
This is line 14. 
This is line 15.
21.7.5 删除行

1.删除连续的空白行
创建包含一个非空白行和一个空白行的地址区间。如果sed编辑器遇到了这个区间,它不会删除。首先匹配区间/./,/$/,最后不删除使用!d

/./,/^$/!d

2.删除开头的空白行
从含有字符的开始到数据流结束,这个区间内的任何行都不会从输出中删除,值得注意的是^$换成了$

/./,$/!d

3.删除结尾的空白行
匹配一个或者多个或者零个的换行符,然后做{$d; N; b start}的相关处理,最后实际的脚本为

$ sed '{ 
> :start 
> /^\n*$/{$d ; N ; b start } 
> }'

21.7.6 删除HTML标签
首先data11.txt内容为:

$ cat data11.txt 
<html> 
<head> 
<title>This is the page title</title> 
</head> 
<body> 
<p> 
This is the <b>first</b> line in the Web page. 
This should provide some <i>useful</i> 
information to use in our sed script. 
</body> 
</html>

如果使用sed指令s/<.*>//g可以发现删除了所有的标签及之间的内容,例如<b>first</b>

$ sed 's/<.*>//g' data11.txt 
 
 
 
 
 
 
This is the  line in the Web page. 
This should provide some 
information to use in our sed script. 
 
 
$

问题的解决办法在于忽略任何嵌入原始标签中的大于号,即s/<[^>]*>//g

$ sed 's/<[^>]*>//g' data11.txt 
 
 
This is the page title 
 
 
 
This is the first line in the Web page. 
This should provide some useful 
information to use in our sed script. 
 
 
$

最后删除多余空白行就行

$ sed 's/<[^>]*>//g ; /^$/d' data11.txt
This is the page title 
This is the first line in the Web page. 
This should provide some useful 
information to use in our sed script. 
$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值