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


20

我的问题与该答案中针对反向greppingsed特定解决方案有关。我无法解读的/ 解决方案如下:sedgrep

sed '1!G;h;$!d' file

有人可以解密此命令吗?

我从VI(M)的知识中知道G代表文件的最后一行,而sed bang(!)和后跟一个地址的工作方式有点像grep -v这样,也就是说它将不匹配该行。但总体而言,上面的内联sed脚本超出了我的范围。


3
...非常缓慢...
mikeserv

1
正如mikeserv的提示。应该注意的是,这种棘手的sed方法是一种极其低效的方式(O(n ^ 2/2)复杂度)来反转文件中的行。对于具有大量行的文件,这将是极其缓慢的。有关更有效的行序反转选择,请参见tacGNU coreutils。
arielf

Answers:


35

这将逐行反转文件。

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

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

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


到命令:

有在此声明3个命令:1!Gh$!d

  • 1!G表示该G命令在除第一行(!否定1)之外的每一行上执行。G表示保留空间中的内容追加到模式空间中。

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

  • $!d适用于除最后一行以外的所有行($代表最后一行,取反!)。d是删除行(图案空间)的命令。


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

1
@Geek否,该h命令将模式空间复制到保持空间,该空间将持续到sed结束。脚本结束后,所有内容都会清除,因为二进制文件已退出。
混乱

2
我们可以把保持空间想像成vim的寄存器吗?他们也编号了吗?还是只有其中之一?
极客2015年

2
@Geek在sed这里只有一个容纳空间。这就像一个可以包含某些内容的变量。
混沌

1
@ user1717828如果不处理,则将打印第一行。由于不调用sed,因此-n我们必须删除除最后一行以外的所有行。sed在最后一行将所有内容(从保留空间到模式空间)追加。并且因为d将不执行命令,所以将打印该行(此行现在包含整个文件的反向)。
混乱

1
(1)OP的子问题/观察(在注释中)为“因此,最后一行h命令有点无操作”。他是对的; 处理输入最后一行时,读取保持空间(以便将其追加到模式空间),然后将模式空间复制到保持空间,空间不再被引用。我们可以说还是。(2)我们可以尽量避免使用说。sedGhsed 'G;$!h;$!d'sed 'G;$!{h;d}'dsed -n 'G;h;$p'
斯科特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.