我对sed中的两个概念感到困惑:持有空间和模式空间.有人可以帮忙解释一下吗?
这是手册的片段:
Run Code Online (Sandbox Code Playgroud)h H Copy/append pattern space to hold space. g G Copy/append hold space to pattern space. n N Read/append the next line of input into the pattern space.
这六个命令真让我迷惑.
Jan*_*ary 98
当sed逐行读取文件时,当前读取的行将插入到模式缓冲区(模式空间)中.模式缓冲区就像临时缓冲区,即存储当前信息的暂存器.告诉sed打印时,它会打印模式缓冲区.
保持缓冲区/保持空间就像一个长期存储,这样你可以捕获一些东西,存储它并在sed处理另一条线时再使用它.您不直接处理保留空间,而是如果要对其执行某些操作,则需要将其复制或附加到模式空间.例如,print命令p仅打印图案空间.同样,s对模式空间进行操作.
这是一个例子:
sed -n '1!G;h;$p'
Run Code Online (Sandbox Code Playgroud)
(-n选项禁止自动打印行)
这里有三个命令:1!G,h和$p.1!G有一个地址,1(第一行),但!该命令将被执行到处手段,但在第一行上.$p另一方面,只会在最后一行执行.那么会发生什么:
h将第一行复制到保留空间.G,将保持缓冲区的内容附加到模式缓冲区,用换行符分隔它.模式空间现在包含第二行,换行符和第一行.h命令将模式缓冲区的连接内容插入到保留空间,该空间现在保持反转的行2和1.最后,在读取完最后一行并且将保持空间(以相反顺序包含所有前面的行)附加到模式空间后,将打印模式空间p.正如您所猜到的,上面完全按照tac命令执行操作 - 反向打印文件.
小智 15
@Ed Morton:在这里不同意你的观点.我发现sed非常有用和简单(一旦你理解了模式的概念并保持缓冲区),就可以提出一种优雅的方式来进行多行grepping.
例如,获取一个包含主机名的文本文件和一些关于每个主机的信息,其间有很多垃圾,我不在乎.
Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Run Code Online (Sandbox Code Playgroud)
对我来说,使用主机名和相应的信息行获取行的awk脚本将比我能用sed做的更多:
sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt
Run Code Online (Sandbox Code Playgroud)
输出看起来像:
Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!
Run Code Online (Sandbox Code Playgroud)
(注意sed在输出中出现两次.)
以上解释:
是的,这是一个简单的例子,但我怀疑这是一个常见的问题,很快就被一个简单的sed单行程处理.对于更复杂的任务,例如您不能依赖于给定的可预测序列的任务,awk可能更适合.
San*_*Lee 10
虽然@ January的答案和例子很好,但对我来说解释还不够.我不得不去搜索和学习很多东西,直到我理解了究竟sed -n '1!G;h;$p'是如何工作的.所以我想详细说明像我这样的人的命令.
首先,让我们看看命令的作用.
$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a
Run Code Online (Sandbox Code Playgroud)
它像tac命令一样反转输入.
sed逐行读取,让我们看看patten空间和每行的保持空间会发生什么.当h命令将模式空间的内容复制到保留空间时,两个空格都具有相同的文本.
Read line Pattern Space / Hold Space Command executed
-----------------------------------------------------------
a a$ h
b b\na$ 1!G;h
c c\nb\na$ 1!G;h
d d\nc\nb\na$ 1!G;h;$p
Run Code Online (Sandbox Code Playgroud)
在最后一行,$p打印d\nc\nb\na$格式为
d
c
b
a
Run Code Online (Sandbox Code Playgroud)
如果要查看每行的模式空间,可以添加l命令.
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a
Run Code Online (Sandbox Code Playgroud)
我发现观看这个视频教程非常有帮助了解sed是如何工作的,因为这个人展示了如何逐步使用每个空间.保持间隔在第4节教程中引用,但如果您不熟悉,我建议您观看所有视频sed.
此外GNU SED文件和布鲁斯·巴内特的桑达教程是非常好的参考.