sed 暂存空间详解

还是先看sed原理图


什么时候会用到模式空间,那就是在有h,x等命令的时候

g  拷贝资料从 hold space。
G  添加资料从 hold space 至 pattern space 。
h  拷贝资料从 pattern space 至 hold space 。
H  添加资料从 pattern space 至 hold space 。

x  交换 hold space 与 pattern space 内容。

那模式空间和暂存空间他们是如何和谐相处的,或者说,暂存空间的存在可以实现什么功能呢?慢慢看


原理:

$ sed -e '/test/h' -e '$G' example

-----在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。

在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。


看下详细的例子把

[root@centos-fuwenchao tmp]# more zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
Paris           IS3              Margot Strong          02/29/82              9 


--

[root@centos-fuwenchao tmp]# sed -e '/JUST/h' -e '$g' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
JUST                   IS1             Xiao Ming                11/30/84              9

解释:我把匹配JUST的行放在暂存空间中,sed接着往下处理,当处理到最后一行的时候,缓存空间和暂存空间互换,所以最后一行输出的是暂存空间的内容

那么H,G和小写的h,g有什么区别呢?

H命令和G命令与hg命令的唯一不同是HGH将模式空间里的内容追加到暂存缓冲区,G将暂存缓冲区里的内容追加到模式空间。

看:

[root@centos-fuwenchao tmp]# sed -e '/JUST/h' -e '$G' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
Paris           IS3              Margot Strong          02/29/82              9 
JUST                   IS1             Xiao Ming                11/30/84              9

解释:原文本的最后一行照常输出了,这是因为大写的G是追加到模式空间,而你不是覆盖!

看:

[root@centos-fuwenchao tmp]# sed -e '/SUST/h' -e '$G' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
Paris           IS3              Margot Strong          02/29/82              9 
SUST                   PS2           Da Ming                   06/01/86              35
解释:小写的h是覆盖暂存区,所以给出的最后一行是最后一个匹配的行

看:

[root@centos-fuwenchao tmp]# sed -e '/SUST/h' -e '$g' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
SUST                   PS2           Da Ming                   06/01/86              35

解释:最后一个匹配的行替换了最后一行

看:

[root@centos-fuwenchao tmp]# sed -e '/SUST/H' -e '$g' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

解释:大些的H追加到暂存区,所以匹配到的两行都保存在暂存区中,替换了原文本的最后一行

看:

[root@centos-fuwenchao tmp]# sed -e '/SUST/H' -e '$G' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30
INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
HEBUT                IS1             John Main               12/03/84              8
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
Paris            PS2             Ann Sreph               09/28/85              10
Paris           IS3              Margot Strong          02/29/82              9 

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

解释:都是大写,匹配到的追加到最后一行,输出!

写到这里有没有一点奇怪的地方,g或者G前面的$是干嘛用的呀,我也不是很清楚呀,那就接着试验呗


[root@centos-fuwenchao tmp]# sed -e '/SUST/H' -e 'G' zckj 
PARIS           PS1            CHARLES CHIN         01/20/86              30

INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32

SUST                  PS2            Lewis Gray              08/11/85              23

SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9

SUST                  PS2            Lewis Gray              08/11/85              23
HEBUT                IS1             John Main               12/03/84              8

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
Paris            PS2             Ann Sreph               09/28/85              10

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
Paris           IS3              Margot Strong          02/29/82              9 

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

他是怎么处理的

解释:如果匹配到对应行,则输出,以后每当有行读到缓冲区时候,不仅输出改行,还把暂存区中的行输出,当有第二次匹配是,追加到暂存区,此时暂存区中保留了两行,而这时再从原文件中读入行时,暂存区的内容就被追加到缓存区中输出,只是,原文件中的每一行都会跟这两行匹配的输出项,如此循环

看完上面的,能不能预测如果用小写的h和g的输出呢

预测一:

H & g的输出------>首先原样输出行,当遇到匹配行时,追加到暂存区,读入下一行是,暂存区替换缓存区,所以输出是首先原样,然后一旦遇到匹配行,则输出全是匹配行

[root@centos-fuwenchao tmp]# sed -e '/SUST/H' -e 'g' zckj



SUST                  PS2            Lewis Gray              08/11/85              23

SUST                  PS2            Lewis Gray              08/11/85              23

SUST                  PS2            Lewis Gray              08/11/85              23

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
[root@centos-fuwenchao tmp]# 

看来我的预测还是有点错误呀,就是没有遇到匹配行时,原行也是输出匹配行,看来他的处理原理是首先匹配行到暂存区,接着才执行下面的命令!

--更新

现在明白了

他是每一行都要做交换的,第一行是,暂存为空,没有匹配,所以交换的时候第一行为空

第二行同理,

第三行匹配到,追加到暂存,做替换,所以第三行替换为一个空行加上一个原行

第五行第六行同理

第七行有匹配到,追加到暂存,此时暂存为空行+匹配1+匹配2,替换第七行

就这往下同理

所以输出就是上面看到的样子啦




预测二:

h & G 的输出------>每原行都变成 原行+匹配行,遇到的二个匹配行时,每行都是第二个匹配行

[root@centos-fuwenchao tmp]# sed -e '/SUST/h' -e 'G' zckj
PARIS           PS1            CHARLES CHIN         01/20/86              30

INDIAN OCEAN  PS2            SUSAN GREEN          04/05/86              32

SUST                  PS2            Lewis Gray              08/11/85              23
SUST                  PS2            Lewis Gray              08/11/85              23
JUST                   IS1             Xiao Ming                11/30/84              9
SUST                  PS2            Lewis Gray              08/11/85              23
HEBUT                IS1             John Main               12/03/84              8
SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
SUST                   PS2           Da Ming                   06/01/86              35
Paris            IS3             PETER Webor           07/05/82              32
SUST                   PS2           Da Ming                   06/01/86              35
Paris            PS2             Ann Sreph               09/28/85              10
SUST                   PS2           Da Ming                   06/01/86              35
Paris           IS3              Margot Strong          02/29/82              9 
SUST                   PS2           Da Ming                   06/01/86              35

还是有点偏差,真不明白了,那就接着再看看有什么发现没有吧!

--更新解释

第一行没有匹配到,暂存空行,缓存第一行,G空第一行后加一个空行

第二行同理

第三行匹配到,往第三行之后在添加一行

接下来就不解释了

那我现在预测小写的h和g就非吹灰之力了把

[root@centos-fuwenchao tmp]# sed -e '/SUST/h' -e 'g' zckj


SUST                  PS2            Lewis Gray              08/11/85              23
SUST                  PS2            Lewis Gray              08/11/85              23
SUST                  PS2            Lewis Gray              08/11/85              23
SUST                   PS2           Da Ming                   06/01/86              35
SUST                   PS2           Da Ming                   06/01/86              35
SUST                   PS2           Da Ming                   06/01/86              35
SUST                   PS2           Da Ming                   06/01/86              35



接着看看 x 的用法吧

x  交换 hold space 与 pattern space 内容。

[root@centos-fuwenchao tmp]# more num.txt 
1
2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/1/h' -e '/8/x' num.txt 
1
2
3
4
5
6
7
1

单向替换,这是什么情况!!!!


---更新

sed -e '/test/h' -e '/check/x' example -----互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。

解释为什么是单向替换吧!!

首先  找到 模式匹配的 1 ,保存到暂存区,接着执行第二条命令,找到 匹配的 8 ;呵呵。这是暂存区是1 ,缓存区是 8 ,替换之后就是上面的输出结果啦,看起来像是单向匹配;

转念一想,这样是不是也可以呢

[root@centos-fuwenchao tmp]# sed -e '/1/h' -e '/8/g' num.txt 
1
2
3
4
5
6
7
1



那如果我想实现双向替换呢

[root@centos-fuwenchao tmp]# sed -e 's/1/8/' -e 's#8#1#' num.txt 
1
2
3
4
5
6
7
1
[root@centos-fuwenchao tmp]# 

这样呢

[root@centos-fuwenchao tmp]# sed -e '/1/H' -e '/8/g' num.txt 
1
2
3
4
5
6
7

1
[root@centos-fuwenchao tmp]# 
(7和1之间有个空行)

写到这我好想明白了点什么!

暂时解决双向替换的问题吧

[root@centos-fuwenchao tmp]# sed -e '/1/H;/8/H' -e '/8/x' num.txt 
1
2
3
4
5
6
7

1
8
[root@centos-fuwenchao tmp]# sed -e '/1/H;/8/H' -e '/8/x' num.txt 
1
2
3
4
5
6
7

1
8
[root@centos-fuwenchao tmp]# sed -e '/1/h;/8/H' -e '/8/x' num.txt 
1
2
3
4
5
6
7
1
8
[root@centos-fuwenchao tmp]# sed -e '/1/h;/8/h' -e '/8/x' num.txt 
1
2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# 

写到这,两个命令的执行顺序貌似是先执行第一个,接着执行第二个

但是再看看

[root@centos-fuwenchao tmp]# sed -e '/1/h;/8/H' -e '/5/x' num.txt 
1
2
3
4
1
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/1/H;/8/H' -e '/5/x' num.txt 
1
2
3
4

1
6
7
8
[root@centos-fuwenchao tmp]# 

看到这,你还会以为他是先执行第一个e,在执行第二个e吗?

什么感觉,他是按照匹配的模式交替顺序进行的吗

[root@centos-fuwenchao tmp]# sed -e 's/2/8/' -e 's#1#7#' num.txt
7
8
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# 

还会那样认为吗?

再看看

[root@centos-fuwenchao tmp]# sed -e '/1/h' -e '/2/G' num.txt
1
2
1
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/5/h' -e '/1/G' num.txt
1

2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# 

我现在的结论是e是并行逐行处理的,往上验证下行不行

现在是不是了解到逐行的含义了

先执行第一行,执行第一个e,接着第二个e

接着第二行,执行第一个e,接着第二个e

接着往下



好吧,上面就是最终版了!


做几个验证

[root@centos-fuwenchao tmp]# sed -e '/1/h' -e '/2/G' num.txt
1
2
1
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/5/h' -e '/1/G' num.txt
1

2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/5/h' -e '/1/g' num.txt

2
3
4
5
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/1/h;/8/H' -e '/5/x' num.txt 
1
2
3
4
1
6
7
8
[root@centos-fuwenchao tmp]# sed -e '/1/h;/5/H' -e '/6/x' num.txt 
1
2
3
4
5
1
5
7
8
[root@centos-fuwenchao tmp]# 


碰到这样一个问题


sed -e ’s/72/70/;/@/{h;s/test/next/g;x;G}’ fmt_vuln.c
要解决这个问题,先解决这个问题为什么是这样的吧,为了解释,我用-分割一下

[root@centos-fuwenchao tmp]# sed -e '/1/h;/5/H' -e '/6/x;G' num.txt 
1
1
-      //匹配到1,缓存1,暂存1,G将暂存1加入缓存1,此时缓存1 1 暂存 1 输出1 1
2
1
-     //同理
3
1
-     // 同理
4
1
-    //同理
5
1
5
-     //缓存5 暂存1 5 ;G将1 5 追加入缓存 ,此时缓存 5 1 5
1
5
6
-   // 缓存 6 暂存 1 5 ;x将他们互换,此时 缓存 1 5 ,暂存6;G将6追加到缓存 ;此时缓存 1 5 6
7
6
-   // 缓存 7 暂存 6 ;G 将6追加到缓存 缓存 7 6
8
6
-  //同理

--
[root@centos-fuwenchao tmp]# sed -e 's/7/345/;/8/{h;s/8/888/;x;G}' num.txt 
1
2
3
4
5
6
345
8
888


都到这了,那个命令就不解释了吧!

加一点吧


一次执行多个命令的方式有三种:
(1) sed 's/w1/& w2/g; 1/i\words' filename   (使用;号把命令隔开,注意前面不加-e参数)
(2) sed -e 'cmd1' -e 'cmd2'  filename     (使用多个-e参数)
再加一点


下一个:n命令 

$ sed '/test/{ n; s/aa/bb/; }' example-----如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。

{ }  集合有相同位址参数的指令。











一次执行多个命令的方式有三种:
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值