现在的位置: 首页 > 综合 > 正文

sed模式空间和暂存空间

2013年05月27日 ⁄ 综合 ⁄ 共 6383字 ⁄ 字号 评论关闭

sed模式空间和暂存空间

sed编辑器逐行处理文件,并将输出结果打印到屏幕上。sed命令将当前处理的行读入模式空间(pattern space)进行处理,sed在该行上执行完所有命令后就将处理好的行打印到屏幕上(除非之前的命令删除了该行),sed处理完一行就将其从模式空间中删除,然后将下一行读入模式空间,进行处理、显示。处理完文件的最后一行,sed便结束运行。sed在临时缓冲区(模式空间)对文件进行处理,所以不会修改原文件,除非显示指明-i选项。

与模式空间和暂存空间(hold space)相关的命令:

n 输出模式空间行,读取下一行替换当前模式空间的行,执行下一条处理命令而非第一条命令。
N
读入下一行,追加到模式空间行后面,此时模式空间有两行。
h
把模式空间里的行拷贝到暂存空间。
H
把模式空间里的行追加到暂存空间。
g
用暂存空间的内容替换模式空间的行。
G
把暂存空间的内容追加到模式空间的行后。
x
将暂存空间的内容于模式空间里的当前行互换。
对所选行以外的所有行应用命令。

注意:暂存空间里默认存储一个空行。

下面是一些例子:

cat datafile
111111111111 aaa
222222222222 bbb
333333333333 ccc
444444444444 ddd
555555555555 eee
666666666666 fff

在每行后面加一空行:

sed ‘G’ datafile
111111111111 aaa

222222222222 bbb

333333333333 ccc

444444444444 ddd

555555555555 eee

666666666666 fff

aaa行被读入模式空间,执行G,在此行后面追加一个空行,然后打印模式空间,其他行同理。

在匹配行后加一空行:

sed ‘/ccc/G’ datafile
111111111111 aaa
222222222222 bbb
333333333333 ccc

444444444444 ddd
555555555555 eee
666666666666 fff

在匹配行前加入一个空行:

sed ‘/ccc/{x;p;x;}’ datafile
111111111111 aaa
222222222222 bbb

333333333333 ccc
444444444444 ddd
555555555555 eee
666666666666 fff

命令执行前后暂存空间和模式空间的变化情况:

命令    
暂存空间                                        模式空间
x          
执行前:null
执行后:ccc\n            
执行前:ccc\n
执行后:null
p         
执行前:null
执行后:ccc\n             执行前:ccc\n
执行后:null
输出一个空行
x         
执行前:ccc\n
执行后:null             执行前:null
执行后:ccc\n
输出ccc所在行

(注:把ccc所在行简写为ccc

删除偶数行:

sed ‘{n;d;}’datafile
111111111111 aaa
333333333333 ccc
555555555555 eee

执行n后打印第一行,然后读入第二行执行d命令,即删除此行;然后在执行n打印第三行,然后读入第四行执行d命令,依此类推。

在偶数行后添加一新行:

sed ‘{n;G;}’ datafile
111111111111 aaa
222222222222 bbb

333333333333 ccc
444444444444 ddd

555555555555 eee
666666666666 fff

执行 n
以后将第一行输出到标准输出以后,然后第二行进入模式空间,根据前面对 G
的解释,会在第二行后面插入一个空行,然后输出;再执行 n
将第三行输出到标准输出,然后第四行进入模式空间,并插入空行,依此类推。
相应的:sed ‘{n;n;G;}’ datafile
表示在文件的第 3,6,9,12,…
行后面插入一个空行。

将偶数行置空:

sed ‘{n;g;}’ datafile
111111111111 aaa

333333333333 ccc

555555555555 eee

执行n后打印第一行,然后读入第二行执行g命令,g命令用暂存空间内容(null)来替换当前模式空间,即第二行被置空。其它行依此类推。

合并偶数行到上一行:

sed ‘{N;s/\n/\t/;}’datafile
111111111111 aaa 222222222222 bbb
333333333333 ccc 444444444444 ddd
555555555555 eee 666666666666 fff

执行N,将第二行追加到模式空间的第一行后,此时模式空间用两行,然后执行替换(s)将第一个换行符替换成tab。其它行依此类推。

加行号,大致相当于cat -n datafile

sed = datafile
1
111111111111 aaa
2
222222222222 bbb
3
333333333333 ccc
4
444444444444 ddd
5
555555555555 eee
6
666666666666 fff

sed = datafile |sed‘{N;s/\n/\t/;}’
1 111111111111 aaa
2 222222222222 bbb
3 333333333333 ccc
4 444444444444 ddd
5 555555555555 eee
6 666666666666 fff

输出文件最后2行,相当于 tail -2 datafile

sed ‘{$!N;$!d;}’datafile
555555555555 eee
666666666666 fff

sed ‘{$!N;$!d;}’ : 对文件倒数第二行以前的行来说,N
将当前行的下一行追加到模式空间中以后,D
就将模式空间的内容删除了;到倒数第二行的时候,将最后一行追加到倒数第二行下面,然后最后一行不执行 d(!对所选行-此处是最后一行,以外的行执行命令),所以文件的最后两行都保存下来了。

将文件的行反序显示,相当于 tac
命令:

sed ‘{1!G;h;$!d;}’datafile
666666666666 fff
555555555555 eee
444444444444 ddd
333333333333 ccc
222222222222 bbb
111111111111 aaa

1!G表示除了第一行以外,其余行都执行G命令;$!d表示除了最后一行以外,其余行都执行d命令。

看一下sed ‘{1!G;h;$!d;}’命令执行过程中暂存空间与模式空间的变化:

处理行       
命令        
暂存空间                                                                         模式空间
第一行        h;d          
执行前:null
执行后:aaa\n                                            执行前:aaa\n
执行后:null
第二行        G;h;d      
执行前:aaa
执行后:bbb\n1111\n                                执行前:bbb\n
执行后:null
最后一行    G;h         
执行前:eee\n…aaa\n
执行后:fff\n…bbb\n\aaa\n     
执行前:eee\n
执行后:fff\n…bbb\n\aaa\n

(注:把各个行简写了)

转载,自己加了点注释和对有些不对的地方的更正。

sed 处理文件时,会把文件的每一行保存在一个临时缓冲区,即模式空间。sed处理完一行后,该模式空间就被清空,下一行等待处理。
因此可把模式空间内容用命令h复制并保存在一个暂存缓冲区(holdingbuffer 保持空间)内,然后可用命令G把它从暂存缓冲区读出,并放回模式空间缓冲区,追加在模式空间内当前行的后面。

例子一
sed G
在文件每一行下面输出一个空行

 

代码:

$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555

$ sed G foo
11111111111111

22222222222222

33333333333333

44444444444444

55555555555555

解释:

sed 中 G 的用法
The G functionappends the contents of the holding area to the contents of the pattern space. The former and new contents are separated by a newline.The maximum number of addresses is two.

hold space : 保持空间(或者叫保留空间、缓冲区),初始为空
pattern space :模式空间

在上面的例子中,将为空的hold space附加到文件的每一行后面,所以结果是每一行后面多了一个空行

引申出:
sed '/^$/d;G'
在文件的每一个非空行下面输出一个空行
sed '/^$/d;G;G'
在文件的每一个非空行下面输出两个空行

 

代码:

$ cat foo
11111111111111
22222222222222

33333333333333
44444444444444
55555555555555

$ sed '/^$/d;G' foo
11111111111111

22222222222222

33333333333333

44444444444444

55555555555555

注:有时会有一些由空格符或者TAB组成的空行,前面的正则式 ^$ 就不能匹配到这样的行,则可以这样

sed'/[[:space:]]/d;G'

例子二
sed'/regex/{x;p;x;}'
在匹配regex的所有行前面插入一个空行

 

代码:

$ cat foo
11111111111111
22222222222222
test33333333333333
44444444444444
55555555555555

$ sed '/test/{x;p;x;}' foo
11111111111111
22222222222222

test33333333333333
44444444444444
55555555555555

解释:
sed 中 x 的用法
The exchangefunction interchanges the contents of the pattern space and the holding area.The maximum number of addresses is two.

即交换保持空间holdspace和模式空间pattern space的内容

sed 中 p 的作用是把模式空间复制到标准输出。

分析一下该命令执行过程中保持空间和模式空间的内容

命令 保持空间 模式空间
x 执行前:null 执行后:test\n执行前:test\n 执行后:null
p 执行前:null 执行后:test\n执行前:test\n 执行后:null 输出一个空行
x 执行前:test\n 执行后:null 执行前:null 执行后:test\n

(注:把test所在的行简写为test了)

引申:
可以试验一下 sed'/test/{x;p;}' foo 或者 sed '/test/{p;x;}' foo 等,看看结果,体会两个空间的变化

相应的:
sed'/regex/G' 是在匹配regex的所有行下面输出一个空行
sed'/regex/{x;p;x;G;}' 是在匹配regex的所有行前面和下面都输出一个空行

例子三
sed'n;G;'
在文件的偶数行下面插入一个空行

 

代码:

$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555

$ sed 'n;G;' foo
11111111111111
22222222222222

33333333333333
44444444444444

55555555555555

解释:
sed 中 n 的用法:将模式空间拷贝于标准输出。用输入的下一行替换模式空间。

执行 n 以后将第一行输出到标准输出以后,然后第二行进入模式空间,根据前面对 G 的解释,会在第二行后面插入一个空行,然后输出;再执行 n 将第三行输出到标准输出,然后第四行进入模式空间,并插入空行,依此类推

相应的:
sed 'n;n;G' 表示在文件的第3,6,9,12,... 行后面插入一个空行
sed 'n;n;n;G' 表示在文件的第4,8,12,16,... 行后面插入一个空行
sed 'n;d' 表示删除文件的偶数行

例子四
sed '$!N;$!D'
输出文件最后2行,相当于 tail -2 foo

 

代码:

$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555

$ sed '$!N;$!D' foo
44444444444444
55555555555555

解释:

D 删除模式空间内第一个 newline 字母 \n 前的资料。
N 把输入的下一行添加到模式空间中。

sed '$!N;$!D' : 对文件倒数第二行以前的行来说,N 将当前行的下一行放到模式空间中以后,D 就将模式空间的内容删除了;到倒数第二行的时候,将最后一行附加到倒数第二行下面,然后最后一行不执行 D ,所以文件的最后两行都保存下来了。

还有 N 的另外一种用法

 

代码:

$ sed = foo | sed N
1
11111111111111
2
22222222222222
3
33333333333333
4
44444444444444
5
55555555555555

$ sed = foo | sed 'N;s/\n/     /'
1         11111111111111
2         22222222222222
3         33333333333333
4         44444444444444
5         55555555555555

解释:
N 的作用是加上行号,可以用于格式化输出文件

例子五
sed'1!G;h;$!d'
sed -n'1!G;h;$p'
将文件的行反序显示,相当于tac 命令(有些平台没有这个命令)

 

代码:

$ cat foo
11111111111111
22222222222222
33333333333333

$ sed '1!G;h;$!d' foo
33333333333333
22222222222222
11111111111111

$ sed -n '1!G;h;$p' foo
33333333333333
22222222222222
11111111111111

解释:
sed 中 h 用法:h
The h (hold)function copies the contents of the pattern space into a holding area,destroying any previous contents of the holding area.

意思是将模式空间的内容保存到保持空间中去

sed 中的 d 表示删除模式空间。

1!G表示除了第一行以外,其余行都执行G命令;$!d表示除了最后一行以外,其余行都执行d命令。

看一下sed '1!G;h;$!d'命令执行过程中保持空间与模式空间的变化:

命令 保持空间 模式空间
第一行 h;d 执行前:null 执行后:1111\n 执行前:1111\n执行后:null
第二行 G;h;d 执行前:1111 执行后:2222\n1111\n 执行前:2222\n 执行后:null
第二行 G;h 执行前:2222\1111\n 执行后:3333\n2222\n\1111\n 执行前:3333\n 执行后:3333\n2222\n\1111\n

(注:把各个行简写了)

这样输出以后就是文件的反序了。

 

 

抱歉!评论已关闭.