sed中“保持空间”和“模式空间”的概念

时间:2012-10-11 06:46:11

标签: linux sed

我对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.

这六个命令让我很困惑。

3 个答案:

答案 0 :(得分:90)

当sed逐行读取文件时,当前读取的行将插入 pattern 缓冲区(模式空间)。模式缓冲区就像临时缓冲区,即存储当前信息的暂存器。告诉sed打印时,它会打印模式缓冲区。

保持缓冲区/保持空间就像一个长期存储,这样你可以捕获一些东西,存储它并在sed处理另一条线时再使用它。您不直接处理保留空间,而是如果要对其执行某些操作,则需要将其复制或附加到模式空间。例如,打印命令p仅打印图案空间。同样,s对模式空间进行操作。

以下是一个例子:

sed -n '1!G;h;$p'

(-n选项禁止自动打印行)

此处有三个命令:1!Gh$p1!G的地址为1(第一行),但!表示该命令将在第一行处执行。另一方面,$p只会在最后一行执行。那么会发生什么:

  1. 读取第一行并自动插入到模式空间
  2. 在第一行,第一个命令不执行; h将第一行复制到暂存空间。
  3. 现在第二行替换了模式空间中的任何内容
  4. 在第二行,首先执行G,将保持缓冲区的内容附加到模式缓冲区,用换行符分隔。模式空间现在包含第二行,换行符和第一行。
  5. 然后,h命令将模式缓冲区的连接内容插入到保留空间,该空间现在保持反转的行2和1。
  6. 我们前往第3行 - 转到上面第(3)点。
  7. 最后,在读取完最后一行并且将保留空间(以相反顺序包含所有前面的行)附加到模式空间后,将使用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在输出中出现两次。)

上面解释说:

  1. -n禁用输出,除非明确打印
  2. 首先匹配,找到并将Host:行放入保留缓冲区(h)
  3. 第二次匹配,找到下一个Info:行,但首先用保持缓冲区交换(x)模式缓冲区中的当前行,然后打印(p)Host:行,然后重新交换(x)并打印(p)信息:行。
  4. 是的,这是一个简单的例子,但我怀疑这是一个常见的问题,很快就被简单的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 documentBruce Barnett's Sed tutorial是非常好的参考资料。

相关问题