我对sed中的两个概念感到困惑:持有空间和模式空间。有人可以帮忙解释一下吗?
以下是手册的片段:
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.
这六个命令让我很困惑。
答案 0 :(得分:90)
当sed逐行读取文件时,当前读取的行将插入 pattern 缓冲区(模式空间)。模式缓冲区就像临时缓冲区,即存储当前信息的暂存器。告诉sed打印时,它会打印模式缓冲区。
保持缓冲区/保持空间就像一个长期存储,这样你可以捕获一些东西,存储它并在sed处理另一条线时再使用它。您不直接处理保留空间,而是如果要对其执行某些操作,则需要将其复制或附加到模式空间。例如,打印命令p
仅打印图案空间。同样,s
对模式空间进行操作。
以下是一个例子:
sed -n '1!G;h;$p'
(-n选项禁止自动打印行)
此处有三个命令:1!G
,h
和$p
。 1!G
的地址为1
(第一行),但!
表示该命令将在第一行但处执行。另一方面,$p
只会在最后一行执行。那么会发生什么:
h
将第一行复制到暂存空间。G
,将保持缓冲区的内容附加到模式缓冲区,用换行符分隔。模式空间现在包含第二行,换行符和第一行。h
命令将模式缓冲区的连接内容插入到保留空间,该空间现在保持反转的行2和1。最后,在读取完最后一行并且将保留空间(以相反顺序包含所有前面的行)附加到模式空间后,将使用p
打印模式空间。正如您所猜测的,上面的内容与tac
命令完全相同 - 反向打印文件。
答案 1 :(得分:12)
@Ed Morton:在这里不同意你的观点。我发现sed非常有用和简单(一旦你理解了模式的概念并保持缓冲区),就可以用一种优雅的方式来进行多行渲染。
示例,获取一个包含主机名的文本文件和一些关于每个主机的信息,其中包含大量垃圾,我不在乎。
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
对我来说,使用主机名和相应信息行获取行的awk脚本将比我能用sed做的更多:
sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt
输出如下:
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!!
(请注意Host: foo1
在输出中出现两次。)
上面解释说:
是的,这是一个简单的例子,但我怀疑这是一个常见的问题,很快就被简单的sed单行处理。对于更复杂的任务,例如你不能依赖于给定的,可预测的序列的任务,awk可能更适合。
答案 2 :(得分:8)
虽然@ 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
它会像tac
命令那样反转输入。
sed
逐行读取,所以让我们看看模式空间和每行的保持空间会发生什么。当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
在最后一行,$p
打印格式为
d\nc\nb\na$
d
c
b
a
如果要查看每一行的模式空间,可以添加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
我发现观看这个视频教程Understanding how sed works非常有帮助,因为这个人展示了每个空间将如何逐步使用。保留间隔在第4节教程中提及,但如果您不熟悉sed
,我建议您观看所有视频。
同样GNU sed document和Bruce Barnett's Sed tutorial是非常好的参考资料。