前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sed的pattern space与hold space应用举例

sed的pattern space与hold space应用举例

作者头像
qsjs
发布2020-06-09 09:11:05
8270
发布2020-06-09 09:11:05
举报
文章被收录于专栏:MyPanda的学习笔记

对于常常使用的sed命令,我们需要知道如下的内容,才能更好的使用它: A. 模式空间: sed 在处理每一行的时候,首先会把要处理的行存入到模式空间里面;然后在模式空间中进行处理,处理完成后,把结果输出,然后释放模式空间。这个模式空间的概念可能听起来有点生疏,其实就是临时缓冲区;换个名称而已;对模式空间的使用举例: 通常把Linux下的文本文件换行符(\n)变为windows下的换行符号(\r\n), 我们不可以直接用:sed 's/\n/\r\n/' FILE , 因为“读入到模式空间”完成后,在模式空间里的行尾的换行符已经没有了,此时再进行替换操作,那么因为没有内容可以匹配而无法成功替换;

代码语言:javascript
复制
[root@localhost ~]# cat testfile.txt
12345
abcdefgs
ASK_MBG.
[root@localhost ~]# cat testfile.txt  | od -An -txC
 31 32 33 34 35 0a 61 62 63 64 65 66 67 73 0a 41
 53 4b 5f 4d 42 47 2e 0a           #结果中有三个0x0a, 表示3行;此为linux格式
[root@localhost ~]#
[root@localhost ~]# sed -i 's/\n/\r\n/' testfile.txt      #直接替换是没有效果的;
[root@localhost ~]# cat testfile.txt  | od -An -txC
 31 32 33 34 35 0a 61 62 63 64 65 66 67 73 0a 41
 53 4b 5f 4d 42 47 2e 0a         #替换后的结果和替换前一样,因为根本没有匹配到
[root@localhost ~]#

要解决这个问题,需要用N命令,追加当前行的后一行的内容到模式空间,然后再做替换操作;因为把两行的内容同时放到模式空间之后, 此时只有模式空间末尾的换行符\n被剔除掉了,所以仍然可以匹配到前一行的换行符,从而实现替换;看下面的结果:

代码语言:javascript
复制
[root@localhost ~]# cat testfile.txt  | od -An -txC
 31 32 33 34 35 0d 0a 61 62 63 64 65 66 67 73 0a
 41 53 4b 5f 4d 42 47 2e 0a  #结果中有个0x0d0a, 表示第一行替换成功;
[root@localhost ~]#
[root@localhost ~]# sed -i '2,$N;s/\n/\r\n/' testfile.txt
[root@localhost ~]# cat testfile.txt  | od -An -txC
 31 32 33 34 35 0d 0a 61 62 63 64 65 66 67 73 0d
 0a 41 53 4b 5f 4d 42 47 2e 0a  #以双数作为开始行,那么这里第二行也替换成功
[root@localhost ~]#

**在上面的结果中,我们看到1,2行都替换成功,但是最后一行还是没有替换,为什么呢? ** 因为是最后一行,所以自然没有下一行,也就不存在把下一行追加到模式空间的说法,所以也就无法替换,但是方法总比问题多:我们先在原始文件后面追加一个空行,然后再按照上面的方式处理就可以了。

代码语言:javascript
复制
[root@localhost ~]# wc -l testfile.txt
3 testfile.txt
[root@localhost ~]# sed -i '$a\ ' testfile.txt     #表示在最后一行之后追加空格
[root@localhost ~]# wc -l testfile.txt
4 testfile.txt
[root@localhost ~]# cat testfile.txt
12345
abcdefgs
ASK_MBG.

[root@localhost ~]#
[root@localhost ~]# cat testfile.txt | od -An -txC
 31 32 33 34 35 0a 61 62 63 64 65 66 67 73 0a 41
 53 4b 5f 4d 42 47 2e 0a 20 0a     #这里看到多了一个0x200a, 表示空格

B. 除了模式空间,还有一个概念叫做 hold space, 中文有叫做"保持空间”的,这也是一种缓冲区,这个缓冲区是不会自动release的;也不会自动把空间的内容进行输出;通常使用hold space的方式是: 在模式空间和hold space之间进行交互,具体有下列:

代码语言:javascript
复制
      h H    Copy/append pattern space to hold space.  #把模式空间的内容 copy或者追加到hold space.

       g G    Copy/append hold space to pattern space. #把hold space的内容copy或者追加到模式空间
       x      Exchange the contents of the hold and pattern spaces. #交换模式空间和hold space的内容;

对于hold space的使用,有一个比较典型的例子是 实现tac的功能:

代码语言:javascript
复制
[root@localhost ~]# cat testfile.txt
12345
abcdefgs
ASK_MBG.
[root@localhost ~]# sed -n '1!G;h;$p' testfile.txt
ASK_MBG.             
abcdefgs                
12345                 
[root@localhost ~]# tac testfile.txt
ASK_MBG.
abcdefgs
12345
[root@localhost ~]#

对上述命令的简要理解如下: pattern space 和hold space 都可以进行追加,也可以进行覆盖. 但是sed在处理的时候,总是首先把要处理的行放到了pattern space, 在这种情况下,我们希望倒序输出,基于以下思考: 首先考虑最简单的两行内容的情况.

  1. 首先读入第一行到pattern space. (无需命令)
  2. 然后从pattern space 放到 hold space.
  3. 把下一行(第二行)读入到pattern space(无需命令). 这时候把 hold space的内容追加到pattern space. 结果是pattern space 的内容变成了 第二行在前面,然后是从hold space 过来的第一行,因此实现了两行的倒序.
  4. 如果有第三行,那么把刚才的pattern space的结果再放到hold space... 这就开始了从上面的步骤2的循环.
  5. 当循环到最后一行的时候,把pattern space的内容进行输出,从而得到倒序的结果.

上面介绍了hold space和pattern space的应用举例,希望你已经get到了哦! 本文原创,转载请注明出处

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档