【问题标题】:How to get the last line that contains \n?如何获取包含 \n 的最后一行?
【发布时间】:2015-10-18 06:58:21
【问题描述】:

根据定义,一行必须以换行符结尾 (\n) (ref.)。但是为了这篇文章的目的,我会将任何一系列字符视为一行,无论它是否以\n结尾。

命令tail -n 1 返回最后一行,无论它是否以\n 结尾。如何从文件中获取以\n 结尾的最后一行,无论此行是文件的最后一行还是倒数第二行?

【问题讨论】:

  • 一种可能的策略是在换行符处拆分并检查最后一组是否为空(最后一行以新行结尾)或不是(最后一行不以新行结尾)。根据该条件,您可以选择最后一组或上一组。
  • 我试过了。问题是 tail 不返回终止 \n 无论它是否存在于文件中。所以信息丢失了。
  • 你必须依靠tail以外的东西来读取文件。
  • (echo a; echo b; echo -n c) |tail -n1 返回“c”; (echo a; echo b; echo c) |tail -n1 返回“c\n”。问题出在哪里?
  • @Remi.b 事实证明,当您将输出保存到 bash 变量时,如果存在最后一行,则会被修剪。无论如何,任何以tail -2 开头的解决方案都应该有很好的性能(如果可以的话,tail 应该一直到最后)。

标签: regex bash file newline tail


【解决方案1】:

这是使用 Perl 的一种方法:

perl -ne '$s = $_ if /\n$/ }{ print $s' file

脚本逐行读取文件的每一行,如果它以\n结尾,则将其分配给变量$s。读取文件后,将打印$s。如果最后一行没有以换行符结束,则打印倒数第二行,如下所示:

$ cat file
first line
second
third$ perl -ne '$s = $_ if /\n$/ }{ print $s' file
second

请注意,我故意留在$ 中以显示提示,由于没有换行符,该提示位于文件最后一行的末尾。

【讨论】:

    【解决方案2】:
    cat -vte file|grep "\$$"|tail -1
    

    这个呢?或其他方式使用 cat -vte

    这样多余的 $ 将被删除:

    echo -en "Enter\nEnter again\nNo enter this time"|cat -vte|grep "\$$"|sed 's/\$$//g'|tail -1
    

    Linux 的+1 变体(Perl 正则表达式,正则前瞻断言,仅显示匹配部分):

    echo -en "Enter\nEnter again\nNo enter this time"|cat -vte|grep -Po ".*(?=\\\$$)"|tail -1
    

    【讨论】:

    • 是的,这似乎工作正常+1。它只是在行尾添加了一个额外的 $ ,但这不是一个大问题。我不知道它是如何工作的。如果您想多解释一下它的工作原理,我将不胜感激
    • 有几种情况(和文件)当你缺少不可见的控制字符并且你想看看发生了什么,所以你尝试通过 cat -vte 使所有不可见的字符可见, 这会将控制字符(以及行尾)替换为其他字符,例如 ^M 或 $。 cat -vte 甚至可以在管道链的后面使用: echo "...."|cat -vte |grep 如果您可以指定一个肯定不会出现在文件中的确切字符,则使用 tr 命令 grep 到然后那个角色把事情改回来。
    • 如果您的 shell 能够很好地处理 ÷ 或 Ł 等特殊字符,那么这些可能是 tr 的最佳选择。
    猜你喜欢
    • 2017-08-03
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 2021-11-19
    相关资源
    最近更新 更多