命令 sed '1!G;h;$!d' 如何反转文件的内容?

Gee*_*eek 22 sed

我的问题与此答案中针对反向 grepping问题sed给出的特定解决方案有关。我无法破译的/解决方案如下:sedgrep

sed '1!G;h;$!d' file
Run Code Online (Sandbox Code Playgroud)

有人可以破译这个命令吗?

我从 VI(M) 知识中知道 G 表示文件的最后一行,并且在 sed 中一个 bang(!) 后跟一个地址有点像grep -v这样,也就是说它不会匹配该行。但总的来说,上面的内联 sed 脚本超出了我的范围。

cha*_*aos 36

这会逐行反转文件。

sed '1!G;h;$!d'文件

首先,sed有一个保持空间和一个模式空间。在专注于该特定命令之前,我们必须区分它们。

sed读取一个新行时,它被加载到模式空间中。因此,每次处理新行时都会覆盖该空间。另一方面,保持空间在整个处理过程中是一致的,并且值可以存储在那里供以后使用。


到命令:

此语句中有 3 个命令:1!G,h$!d

  • 1!G意味着该G命令在除第一行之外的每一行上执行(!否定1)。G意味着保持空间中的内容附加到模式空间中。

  • h适用于每一行。它将模式空间复制到保持空间(并覆盖它)。

  • $!d适用于除最后一行之外的每一行($代表最后一行,!否定它)。d是删除行(模式空间)的命令。


  1. 现在,当读取第一行时,sed执行h命令。第一行被复制到保留空间中。然后它被删除,因为它符合$!条件。sed继续第二行。
  2. 第二行与条件匹配1!(它不是第一行),因此保持空间(有第一行)被附加到模式空间(有第二行)。之后,在模式空间中,现在有第二行,然后是第一行,由换行符分隔。现在,该h命令适用(如每一行);模式空间中的所有内容都被复制到保持空间中。第三条语句 ( $!d) 适用:该行从模式空间中删除。
  3. 现在所有行都完成了第 2 步。我们跳到最后一行。
  4. 在最后一行 ( $) 中,几乎所有的步骤 2 都完成了,但没有完成删除部分 ( d)。sed,在不带 的情况下调用-n时,在每个输入行的处理结束时自动打印模式空间。因此,当未删除时,将打印模式空间。它现在包含所有反向顺序的行

  • 我们可以把保持空间想象成 vim 的寄存器吗?他们也有编号吗?还是只有其中之一? (2认同)
  • @Geek 在 `sed` 中只有一个保存空间。它就像一个可以包含某些东西的变量。 (2认同)
  • (1) OP 的子问题/观察(在评论中)是,“所以最后一行的‘h’命令是一种无操作。” (增加了强调,并稍加解释)。他是对的; *当“sed”处理输入的**最后一行*时,“G”读取保留空间(以便将其附加到模式空间),然后“h”将模式空间复制到保留空间,*不再被引用*。我们也可以说 `sed 'G;$!h;$!d'` 或 `sed 'G;$!{h;d}'`。(2) 我们可以通过说“sed -n 'G;h;$p'”来避免使用“d”。 (2认同)