侧边栏壁纸
博主头像
枕头下放双臭袜子博主等级

今我何功德,曾不事农桑

  • 累计撰写 162 篇文章
  • 累计创建 30 个标签
  • 累计收到 0 条评论

sed的模式空间与暂存(保持)空间

枕头下放双臭袜子
2020-07-05 / 0 评论 / 0 点赞 / 1,658 阅读 / 0 字 / 正在检测是否收录...

1、sed原理:

sed是一种在线的、非交互式的编辑器。它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed command处理模式空间的内容。处理完成后,把模式空间的内容送往屏幕。然后继续处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出或者 i 选项。

image.png

2、模式空间与暂存空间

多行处理:

一般情况下,如上图所示般sed读取一行处理一行输出一行,清空模式空间,然后重复这个步骤直到文件结束;由于某些特殊情况下用户希望模式空间可以保留到下一次处理,也就是使得sed可以对多行处理之后在输出处理结果。所以在这种需求下,就需要涉及到模式空间、暂存空间两个缓存区之间的数据交换:

模式空间呢,是在实时的一行一行对文本数据进行处理,一次也只会处理一行,而暂存空间相当于一个临时的仓库,在sed进行数据处理的时候,可以作为数据的暂存区域。暂存区域默认有一个换行符存在

image.png

3、操作暂存空间与模式空间处理值的sed command

h 把 模式空间 里的内容 覆盖暂存缓冲区

H 把 模式空间 里的内容 追加暂存缓冲区

g 把 暂存缓冲区 里的内容 覆盖模式空间,覆盖原有的内容

G 把 暂存缓冲区 的内容 追加模式空间 里,追加在原有内容的后面

小写覆盖,大写追加( 我个人为了方便记忆,把h、H记为high,根据上图的暂存空间与模式控件的位置,这样就记忆的比较深不会弄混 )

x 交换暂存缓冲区与模式空间的内容

4、小栗子:

① 使用sed的 G命令 从暂存空间拿回其默认存在的换行符对 “show”文本进行处理,处理一行拿回一个换行符 追加 到原来的 “show” 文本
② 使用sed的 g命令 从暂存空间拿回换行符覆盖原来的文本,处理一行覆盖一行,原来的文本有3行数据,所以便有了3行空白行
image.png

一个非常有意思的例子:
这个例子的执行过程捉摸透了,说明你就弄懂了模式空间与暂存空间。

Tips:

    1!G 第一行不执行G命令,从第二行开始执行
    $!h 最后一行不追加到暂存空间,其余行全追加
    $!d 最后一行不删除,其余行全删
image.png

这行sed的执行结果就是将文本倒装,其实和tac命令( 有没有发现tac就是倒过来的cat ,哈哈,名称相反,作用也相反 )的处理结果是一样的。

那不卖关子了,解读一下这个倒装文本的sed的执行过程:

# sed  -r  '1!G;$!h;$!d'  file

首先请仔细看一下上文的 “ 多行处理 ”个人理解,sed涉及到模式空间与暂存空间之后就变成了 “ 连续对多行处理之后才输出 ” 的情况;
本命令的大致流程是,对文本的每一行执行 “ 1!G;$!h;$!d ”,然后输出

1!G 首先第一行不需要把暂存空间的换行符追加到模式空间,$!h 第一行需要将此行数据覆盖到暂存空间,此时暂存空间的内容只有第一行的数据,然后 $!d 需要删除模式空间的所有内容,此时模式空间为空;

接着处理第二行,1!G 此时需要将暂存空间内第一行的数据追加到模式空间第二行的后边,此时模式空间的数据顺序为第二行、第一行,$!h 此时模式空间的逆序第二行、第一行数据需要覆盖到暂存空间,$!d 删除模式空间的数据;

处理第三行,1!G 此时需要将暂存空间内逆序的两行数据追加到模式空间第三行数据的后边,此时模式空间的数据已经全部成为逆序排列了,$!h 因为已经处理到文本的最后一行即第三行了,此时不需要将数据覆盖到暂存空间,$!d 同样此时不需要删除模式空间的数据了,然后输出模式空间已经排列好的逆序数据!

虽然过程有点复杂,远远不如一个tac来的省事儿,但是不得不说 “ 妙啊 ”!

0

评论