通过几个例子看sed的模式空间与保持空间

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

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

代码:


$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555

$ sed G foo
11111111111111

22222222222222

33333333333333

44444444444444

55555555555555


解释:
sed 中 G 的用法
The G function appends 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'
比如:

zhaoyj]# cat test.txt
AAA

                         #正常的空行

BBBB
                  #由Tab组成的空行
AAABBBB
          #由空格组成的空行
CCOCC

                        #正常的空行

DD

zhaoyj]# sed '/[[:space:]]/d' test.txt  #删除由tab和空格组成的空行
AAA

BBBB
AAABBBB
CCOCC

DD


zaoyj]# sed '/^$/d' test.txt #删除空行
AAA
BBBB
  

AAABBBB
         

CCOCC
DD


zhaoyj]# sed -e '/[[:space:]]/d' -e '/^$/d' test.txt   #删除各种空行
AAA
BBBB
AAABBBB
CCOCC
DD

例子二
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 exchange function interchanges the contents of the pattern space and the holding area. The maximum number of addresses is two.
即交换保持空间hold space和模式空间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 等,看看结果,体会两个空间的变化

注意:第一列是行号,根据行号来比较一下输出

zhaoyj]# sed '/test/x' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222

4 4444
5 5555555
 zhaoyj]# sed '/test/{x;x;x;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222

4 4444
5 5555555
zhaoyj]# sed '/test/{x;p;x;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222

4 test333
5 4444
6 5555555
zhaoyj]# sed '/test/{p;x;p;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222
3 test333


6 4444
7 5555555
zhaoyj]# sed '/test/{p;x;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222
3 test333

5 4444
6 5555555
zhaoyj]# sed '/test/{x;p;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222


5 4444
6 5555555
 


zhaoyj]# sed '/test/{p;p;p;}' test.txt |awk '{print NR"/t"$0}'
1 11111
2 22222
3 test333
4 test333
5 test333
6 test333
7 4444
8 5555555

代码:


$ 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


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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值