sed中“hold space”和“pattern space”的概念

我很困惑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. 

这六个命令让我很困惑。

当sed逐行读取文件时,将当前读取的行插入到模式缓冲区(模式空间)中。 模式缓冲区就像临时缓冲区,暂存当前信息的暂存区。 当你告诉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命令将模式缓冲区的连接内容插入保持空间,该空间现在保持反转的第二行和第一行。
  6. 我们继续第三行 – 去上面第(3)点。

最后,在读完最后一行之后,保留空间(包含所有先前的行以相反的顺序)已被添加到模式空间,模式空间将被打印为p 。 正如你所猜测的那样,上面所做的就是tac命令的function – 反向打印文件。

@ Mort 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 

对我来说,一个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. 首先匹配,find并把主机:行放入暂停缓冲区(小时)
  3. 第二个匹配,find下一个Info:行,但是首先与缓冲区交换(x)模式缓冲区中的当前行,并打印(p)Host:行,然后重新交换(x)并打印(p)Info:线。

是的,这是一个简单的例子,但我怀疑这是一个普遍的问题,很快就被一个简单的sed单线程所处理。 对于更复杂的任务,例如不能依赖给定的可预测序列的任务,awk可能更适合。

尽pipe@一月的回答和这个例子很好,但对我来说,这个解释是不够的。 我不得不search和学习了很多东西,直到我明白了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命令那样反转input。

sed逐行读取,所以让我们看看在每一行的模式空间保持空间上会发生什么。 当h命令将模式空间的内容复制到保持空间时,两个空格都具有相同的文本。

 Read line Pattern Space / Hold Space Command executed ----------------------------------------------------------- aa$ h bb\na$ 1!G;h cc\nb\na$ 1!G;h dd\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 

我发现看这个video教程非常有帮助了解sed是如何工作的 ,因为这个家伙展示了如何逐步使用每个空间。 在第四个教程中提到了间隔,但是如果你不熟悉sed ,我build议你观看所有的video。

另外GNU sed文档和Bruce Barnett的Sed教程是很好的参考。