Linux -- sed命令(4)

2 多行删除命令
单行删除命令d用来删除模式空间中的当前行。但和 N 命令一起使用时,使用单行删除命令就要小心了。

$ sed ‘N ; /System\nAdministrator/d’ data4.txt
All System Administrators should attend.
删除命令会在不同的行中查找单词System和Administrator,然后在模式空间中将两行都删掉。这未必是你想要的结果。

sed编辑器提供了多行删除命令D,它只删除模式空间中的第一行。该命令会删除到换行符(含
换行符)为止的所有字符。

$ sed ‘N ; /System\nAdministrator/D’ data4.txt
Administrator’s group meeting will be held.
All System Administrators should attend.
文本的第二行被 N 命令加到了模式空间,但仍然完好。如果需要删掉目标数据字符串所在行的前一文本行,它能派得上用场。

这里有个例子,它会删除数据流中出现在第一行前的空白行。

$ cat data5.txt

This is the header line.
This is a data line.
This is the last line.
$ sed ‘/^$/{N ; /header/D}’ data5.txt
This is the header line.
This is a data line.
This is the last line.
sed编辑器脚本会查找空白行,然后用 N 命令来将下一文本行添加到模式空间。如果新的模式空间内容含有单词header,则 D 命令会删除模式空间中的第一行。如果不结合使用N命令和D命令,就不可能在不删除其他空白行的情况下只删除第一个空白行。

  1. 多行打印命令
    现在,你可能已经了解了单行和多行版本命令间的差异。多行打印命令P沿用了同样的方法,它只打印多行模式空间中的第一行。这包括模式空间中直到换行符为止的所有字符。当你用-n选项来阻止脚本输出时,它和显示文本的单行p命令的用法大同小异。

$ sed -n ‘N ; /System\nAdministrator/P’ data3.txt
On Tuesday, the Linux System
当多行匹配出现时,P命令只会打印模式空间中的第一行。多行P命令的强大之处在和N命令
及D命令组合使用时才能显现出来。

D命令的独特之处在于强制sed编辑器返回到脚本的起始处,对同一模式空间中的内容重新执行这些命令(它不会从数据流中读取新的文本行)。在命令脚本中加入N命令,你就能单步扫过整个模式空间,将多行一起匹配。

使用P命令打印出第一行,然后用D命令删除第一行并绕回到脚本的起始处。一旦返
回,N命令会读取下一行文本并重新开始这个过程。这个循环会一直继续下去,直到数据流结束。

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

sed编辑器有另一块称作保持空间(hold space)的缓冲区域。在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。有5条命令可用来操作保持空间。

表1 sed编辑器的保持空间命令

命 令 描 述
h 将模式空间复制到保持空间
H 将模式空间附加到保持空间
g 将保持空间复制到模式空间
G 将保持空间附加到模式空间
x 交换模式空间和保持空间的内容
这些命令用来将文本从模式空间复制到保持空间。这可以清空模式空间来加载其他要处理的字符串。

通常,在使用 h 或 H 命令将字符串移动到保持空间后,最终还要用 g 、 G 或 x 命令将保存的字符串移回模式空间(否则,你就不用在一开始考虑保存它们了)。由于有两个缓冲区域,弄明白哪行文本在哪个缓冲区域有时会比较麻烦。这里有个简短的例子演示了如何用 h 和 g 命令来将数据在sed编辑器缓冲空间之间移动。

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.

我们来一步一步看上面这个代码例子:
(1) sed脚本在地址中用正则表达式来过滤出含有单词first的行;
(2) 当含有单词first的行出现时,h命令将该行放到保持空间;
(3) p命令打印模式空间也就是第一个数据行的内容;
(4) n命令提取数据流中的下一行( This is the second data line ),并将它放到模式
空间;
(5) p命令打印模式空间的内容,现在是第二个数据行;
(6) g命令将保持空间的内容( This is the first data line )放回模式空间,替换当
前文本;
(7) p命令打印模式空间的当前内容,现在变回第一个数据行了。

通过使用保持空间来回移动文本行,你可以强制输出中第一个数据行出现在第二个数据行后面。如果丢掉了第一个 p 命令,你可以以相反的顺序输出这两行。

​```shell
$ sed -n ‘/first/ {h ; n ; p ; g ; p }’ data2.txt
This is the second data line.
This is the first data line.
这是个有用的开端。你可以用这种方法来创建一个sed脚本将整个文件的文本行反转!但要那么做的话,你需要了解sed编辑器的排除特性,也就是下节的内容。

五、排除命令
排除命令用于配置命令使其不要作用到数据流中的特定地址或地址区间。感叹号命令!用来排除( negate )命令,也就是让原本会起作用的命令不起作用。下面的例子演示了这一特性。

$ sed -n ‘/header/!p’ data2.txt
This is the first data line.
This is the second data line.
This is the last line.
普通p命令只打印data2文件中包含单词header的那行。加了感叹号之后,情况就相反了:除了包含单词header那一行外,文件中其他所有的行都被打印出来了。

感叹号在有些应用中用起来很方便。之前遇到的一种情况:sed编辑器无法处理数据流中最后一行文本,因为之后再没有其他行了。可以用感叹号来解决这个问题。

$ sed 'N;

s/System\nAdministrator/Desktop\nUser/
s/System Administrator/Desktop User/
’ data4.txt
On Tuesday, the Linux Desktop
User’s group meeting will be held.
All System Administrators should attend.
$ sed '$!N;
s/System\nAdministrator/Desktop\nUser/
s/System Administrator/Desktop User/
’ data4.txt
On Tuesday, the Linux Desktop
User’s group meeting will be held.
All Desktop Users should attend.
这个例子演示了如何配合使用感叹号与 N 命令以及与美元符特殊地址。美元符表示数据流中的最后一行文本,所以当sed编辑器到了最后一行时,它没有执行 N 命令,但它对所有其他行都执
行了这个命令。

使用这种方法,你可以反转数据流中文本行的顺序。要实现这个效果(先显示最后一行,最
后显示第一行),你得利用保持空间做一些特别的铺垫工作。

你得像这样使用模式空间:

(1) 在模式空间中放置一行;
(2) 将模式空间中的行放到保持空间中;
(3) 在模式空间中放入下一行;
(4) 将保持空间附加到模式空间后;
(5) 将模式空间中的所有内容都放到保持空间中;
(6)重复执行第(3)~(5)步,直到所有行都反序放到了保持空间中;
(7) 提取并打印行。
图21-1详细描述了这个过程。
在使用这种方法时,你不想在处理时打印行。这意味着要使用 sed 的 -n 命令行选项。下一步
是决定如何将保持空间文本附加到模式空间文本后面。这可以用 G 命令完成。唯一的问题是你不
想将保持空间附加到要处理的第一行文本后面。这可以用感叹号命令轻松解决:
1!G
下一步就是将新的模式空间(含有已反转的行)放到保持空间。这也非常简单,只要用 h 命
令就行。
将模式空间中的整个数据流都反转了之后,你要做的就是打印结果。当到达数据流中的最后
一行时,你就知道已经得到了模式空间的整个数据流。打印结果要用下面的命令:
$p
这些都是你创建可以反转行的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 ‘{1!G ; h ; $p }’ data2.txt
This is the last line.
This is the second data line.
This is the first data line.
This is the header line.
sed编辑器脚本的执行和预期的一样。脚本输出反转了文本文件中原来的行。这展示了在sed
脚本中使用保持空间的强大之处。它提供了一种在脚本输出中控制行顺序的简单办法。

有个Linux命令已经有反转文本文件的功能了。 tac 命令会倒序显示一个文本文件。这个命令的名字很巧妙,它执行的正好是与 cat 命令相反的功能。

六、分支命令
前面了解到可以使用!来排除不想要操作的行,但如果要对这些行进行其他的操作时就要用到分支命令了.

分支( branch )命令 b 的格式如下:

[ address ]b [ label ]

address 参数决定了哪些行的数据会触发分支命令。 label 参数定义了要跳转到的位置。你可以定义多种label对不同类的行进行不同的操作。

$ sed '{/2/b jump1; /3/b jump2; s/test/No jump/

:jump1 s/test/Jump1 here/
:jump2 s/test/Jump2 here/}’ test
No jump 1
Jump1 here 2
Jump2 here 3
No jump 4
满足标签12的,执行s/test/Jump1 here/命令;满足标签23的,执行s/test/Jump2 here/命令;其他的执行s/test/No jump/命令。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值