Pattern space和Hold space
Sed是对数据流进行操作的一个强大的工具,大家已经经常使用到sed对文本进行修改,替换。这里就不介绍sed的使用方法了,本文主要介绍sed中的Pattern space和Hold space。理解了这两个概念有助于从本质上理解sed处理数据流的方式,尤其是像实现逆转、只输出奇数或偶数行等等功能,Pattern space和Hold space即模式空间和保留空间(也可以称之为缓冲区),保留空间的初始为空,我们可以认为是一个空行。下面图示了sed中的输入流,输出流,模式空间以及保留空间:
先简单介绍下sed的一般工作模式(在没有利用到Hold space的时候),pattern space每次从input中取一行数据到pattern space中,然后经过一些处理,将一行数据放入output中,然后output会输出到屏幕(默认为屏幕,也可以是文件)。记住,此时pattern space还储存着这一行数据,直到input再放入第二行数据取代第一行数据。
当sed的命令为sed [-n] ‘[hHgGx]p’file格式时,需要涉及到hold space,其实我们可以简单的讲hold space理解为sed的一个缓冲区就好了,只是这个缓冲区不会直接进行输出,并且只有pattern space可以对其进行操作,放入或者拿出数据(如上图所示)。
下面解释下[hHgGx]这几个参数:(以file做例子,file中的数据为:
)
Man sed中的解释为:
h/H:copy/append pattern space to hold space(复制或者追加模式空间的数据至保留空间);
g/G:copy/append hold space to pattern space(复制或者追加保留空间的数据至模式空间);
x:exchange the contents of pattern space and hold space(交换模式空间和保留空间的数据);
一般会将h/H和g/G以及x联合起来用,可以达到栈和队列的使用目的。
G:sed 'G' file
因为hold space的初始为一个空行,并且始终没有修改其中的数据,一直保持的是空行,所以在每次执行G命令时,会将空行追加到每行数据之后。
x:sed 'x;G' file
因为开始x命令将hold space的空行和pattern space中的111111111交换,然后G命令又将111111111追加到pattern apace的空行之后,然后输出了
,此时hold space中依旧为111111111,接着pattern space中进入22222222,x命令将hold space的111111111和pattern space中的22222222交换,然后G命令又将22222222追加到pattern apace的111111111之后,然后输出了
,依次类推,就输出了结果。可是看到过程如表格所示:
命令 |
sed 'x;G' file |
|
|
|
|
|
hold space |
|
pattern space |
|
|
执行命令过程 |
执行前 |
执行后 |
执行前 |
执行后 |
输出 |
执行x命令 |
空行 |
111111111 |
111111111 |
空行 |
无输出 |
执行G命令 |
111111111 |
111111111 |
空行 |
空行 111111111 |
|
执行x命令 |
111111111 |
22222222 |
22222222 |
111111111 |
无输出 |
执行G命令 |
22222222 |
22222222 |
111111111 |
111111111 22222222 |
|
执行x命令 |
22222222 |
3333333 |
3333333 |
22222222 |
无输出 |
执行G命令 |
3333333 |
3333333 |
22222222 |
22222222 3333333 |
|
执行x命令 |
……………………………… |
|
|
|
|
大家应该能思考到为什么最后只有一个9 |
|
|
|
|
|
h:sed 'h;G' file
命令进行操作的思路,大家可以参照x命令的方法进行一步步的演示。
H:sed 'H;x' file
g:sed '1h;g;x' file
下面解释下'1h;g;x'中“1“的含义,表示只有第一行执行h命令,将111111111复制到hold space中去,之后每次执行g命令的时候,都是从hold space中将111111111复制出来,覆盖掉了pattern space中的数据,所以结果显示为打印了9行111111111。
而$表示只有最后一行执行这个命令。
在1或$和命令中添加“!“,表示只有第一行或者最后一行不执行这个命令。
有关于更改多的命令n/N、d/D等,请大家自己查阅man sed或者其他资料。在遇到复杂的命令的时候,希望大家可以手动进行画图来执行每个命令,这样就比较清楚了。
下面有4个例子来解释下选项n的作用:
- sed '' file,这句命令会将output中的数据进行输出:
- sed -n 'p' file,这句命令虽然显示的结果和上一个一样,但机制是不同的,这句命令是要求输出pattern space中的数据;如果大家觉得这个说法有点模糊,再继续看下面的例子。
- sed 'p' file,先看结果:
这条命令输出了两遍,为什么呢?因为不仅将每次output中的数据进行了输出,接着又将pattern space中的数据再要求输出一次。
- sed -n '' file,大家应该能猜到这个输出什么结果了,那就是空,因为选项-n指明了要讲pattern space中的数据进行输出,而缺少了p命令,所以不能将pattern space中的数据进行输出。