Skip to content

20.33 如何将一个文本文件倒序输出

https://scz.617.cn/unix/201512241740.txt

Q:

如何将bar文件内容倒序输出?

$ cat bar 1 c 3 e 5 a 4 d 2 b

A:

据说有个tac命令(就是cat反过来写),不过很多系统没有tac可用。一般来说,可以 用sed实现:

$ sed '1!G;h;$!d' bar 2 b 4 d 5 a 3 e 1 c

D: scz 2015-12-24 17:40

参看sed(1)。

sed逐行处理文本。每读取一行,存到pattern space中;针对pattern space进行处 理,可能有一系列命令处理pattern space;处理完毕,显示pattern space中的内容; 读取下一行,重复整个过程直至文件结束。

除了pattern space,sed还提供了一个hold space,用于临时存储某些数据。

sed有一些操作pattern space、hold space的高级命令:

n 读取下一行覆盖pattern space N 读取下一行append到pattern space\n后 g 用hold space中内容覆盖pattern space G 将hold space中内容append到pattern space\n后 h 用pattern space中内容覆盖hold space H 将pattern space中内容append到hold space\n后 d 删除pattern space中内容,新读取下一行到pattern space中 D 删除pattern space中多行内容的第一行,不新读取下一行

s/regexp/replacement/

针对pattern space进行正则匹配

& replacement中可以使用&,引用pattern space中正则匹配命中的内容

下面解释'1!G;h;$!d':

1!G 对第一行不执行G命令,从第二行开始执行 h 用pattern space中内容覆盖hold space $!d 对最后一行不执行d命令

这下就可以理解为什么最终倒序输出整个文本文件。我想说,sed太NB。

处理到最后一行时,pattern space、hold space中实际保存了所有行,只不过是倒 序的。因此这个方案受制于pattern space、hold space的大小,如果待处理文本行 数过多,sed肯定会失败。

D: scz 2015-12-25 10:03

$ awk '{x[NR]=$0}END{for(i=NR;i>0;i--)print x[i]}' bar 2 b 4 d 5 a 3 e 1 c

这里的x[]相当于sed的hold space。FNR、NR从1开始计,不是从0开始。