【问题标题】:How to reverse lines of a text file?如何反转文本文件的行?
【发布时间】:2010-09-29 22:00:36
【问题描述】:

我正在编写一个需要反转文本文件行的小型 shell 脚本。有没有标准的过滤命令来做这种事情?

我的具体应用是我正在获取一个 Git 提交标识符列表,我想以相反的顺序处理它们:

git log --pretty=oneline work...master | grep -v DEBUG: | cut -d' ' -f1 | reverse

我想出的最好办法是像这样实现reverse

... | cat -b | sort -rn | cut -f2-

这使用cat 对每一行进行编号,然后使用sort 按数字降序对它们进行排序(最终反转整个文件),然后使用cut 删除不需要的行号。

以上内容适用于我的应用程序,但在一般情况下可能会失败,因为cat -b 仅对非空行进行编号。

有没有更好、更通用的方法来做到这一点?

【问题讨论】:

标签: shell command-line filter reverse


【解决方案1】:
awk '{a[i++]=$0}END{for(;i-->0;)print a[i]}'

sed 更快,并且兼容openwrt 等嵌入式设备。

【讨论】:

    【解决方案2】:

    在这种情况下,只需使用--reverse

    $ git log --reverse --pretty=oneline work...master | grep -v DEBUG: | cut -d' ' -f1
    

    【讨论】:

      【解决方案3】:
      rev <name of your text file.txt>
      

      你甚至可以这样做:

      echo <whatever you want to type>|rev
      

      【讨论】:

      • 这是另一个问题的好答案。 rev 命令反转每一行中的文本; OP 正在寻找tac,它首先打印最后一行,然后是倒数第二行,以此类推。
      【解决方案4】:

      有一个标准命令供您使用:

      tail -r file.txt
      

      以相反的顺序打印 file.txt 的行!

      【讨论】:

      • POSIX specification for tail 没有提到-r 选项
      • 我正在使用 Mac OS X 10.6 提供的尾部。它的手册页可以追溯到 1993 年(!),并提到“tail 命令出现在 PWB UNIX 中”。所以它肯定已经存在了一段时间......虽然我不知道它是否符合 POSIX。
      • OS X 10.7 上的手册页说:“tail 实用程序应该是 IEEE Std 1003.2-1992 (``POSIX.2'') 规范的超集。特别是 - F、-b 和 -r 选项是对该标准的扩展。”
      • @Wes:好吧好吧!所以它是一个扩展。但我希望它对我们的提问者有用。你说什么?
      • 仅供参考,行数有限,因此不适用于大文件/流,但对中小型文件非常有用。因此,如果您处理一定大小的文件,只需进行测试
      【解决方案5】:

      答案不是 42,而是 tac

      编辑:使用sed会更慢但更消耗内存

      sed 'x;1!H;$!d;x'
      

      甚至更长

      perl -e'print reverse<>'
      

      【讨论】:

      • 神秘的,但这正是我要找的。谢谢!
      • 'tac' 并不神秘:它是相反的'cat'。 ;-)
      • 确实如此,但如果事先不知道,我肯定不会猜到这一点。您可以将排序程序称为“abc”,它以同样的方式有意义,但不会帮助别人猜出它的名字!
      • 在 msysgit 中,我没有 tac,但我有 sed。谢谢!
      【解决方案6】:

      类似于上面的 sed 示例,使用 perl - 可能更令人难忘(取决于您的大脑是如何连接的):

      perl -e 'print reverse <>'
      

      【讨论】:

        【解决方案7】:
        cat -b 仅对非空行进行编号"


        如果这是您要避免的唯一问题,那么为什么不使用“cat -n”对所有行进行编号?

        【讨论】:

        • 好点,我想我没有通过手册页阅读足够多的内容来找到 -n。无论如何,tac 是我真正想要的。
        【解决方案8】:
        :   "@(#)$Id: reverse.sh,v 1.2 1997/06/02 21:45:00 johnl Exp $"
        #
        #   Reverse the order of the lines in each file
        
        awk ' { printf("%d:%s\n", NR, $0);}' $* |
        sort -t: +0nr -1 |
        sed 's/^[0-9][0-9]*://'
        

        对我来说就像一个魅力......

        【讨论】:

        • O(N.log(N)) 与 O(N) tacsed = 您想不出的效率较低的方法?我认为可能有 O(N!),尝试找到它。
        • 我每个月使用它几次,通常在多达几百行代码上。这很好。如果我每天都需要它,在千兆字节的文件上,那么我会重新考虑。我写于 1989 年;我在 1997 年更改了 ID 字符串表示法。它是稳定的代码。而且 'tac' 在 Solaris 上不是标准的。
        • 但是我猜想在 Solaris 上有 sed,因此你可以使用更有效的 sed 'x;1!H;$!d;x'
        • 可能 - 我不使用它来处理如此大的文件,如果需要,排序会将数据溢出到磁盘很重要,但是如果没有可用的内存空间,sed 版本会崩溃。如果是性能问题,我会考虑搬家;它不是(对我来说)所以我可能懒得改变。
        • 这是真的。 sed 不像 sort 那样将数据缓存到磁盘。我不知道 tac 是否不受相同错误的影响 ;-)
        【解决方案9】:

        【讨论】:

        • 它也可以在 MacOS 上使用,但名称为 gtac(当然首先使用 brew 安装 coreutils)
        猜你喜欢
        • 2010-10-19
        • 1970-01-01
        • 2019-10-07
        • 2018-08-12
        • 1970-01-01
        • 2015-07-03
        • 2021-12-30
        • 1970-01-01
        相关资源
        最近更新 更多