【问题标题】:Bash: Strip trailing linebreak from outputBash:从输出中去除尾随换行符
【发布时间】:2012-09-13 12:12:59
【问题描述】:

当我在 Bash 中执行命令时(或者更确切地说,wc -l < log.txt),输出后面会包含一个换行符。我该如何摆脱它?

【问题讨论】:

    标签: bash newline line-breaks


    【解决方案1】:

    添加此内容以供我参考 ^_^

    您还可以使用 bash 扩展魔法从输出中删除一个新行

    VAR=$'helloworld\n'
    
    CLEANED="${VAR%$'\n'}"
    
    echo "${CLEANED}"
    

    【讨论】:

      【解决方案2】:

      使用 awk:

      awk -v ORS="" '1' log.txt 
      

      说明:

      1. -v 为 ORS 赋值
      2. ORS - 输出记录分隔符设置为空白。这将用“”替换新行(输入记录分隔符)

      【讨论】:

      • -1 (虽然我实际上并没有按下它的按钮,因为我只被允许更改一次)。这会删除 所有 换行符,而不仅仅是任何前导或尾随的换行符。
      【解决方案3】:

      如果您想在 Bash 中不带行尾地打印任何内容,请使用 -n 开关回显它。

      如果您已经将它放在变量中,则使用裁剪后的trailing newline 回显它:

      $ testvar=$(wc -l < log.txt)
      $ echo -n $testvar
      

      或者您可以在一行中完成:

      $ echo -n $(wc -l < log.txt)
      

      【讨论】:

      • 该变量在技术上是不必要的。 echo -n $(wc -l &lt; log.txt) 效果一样。
      【解决方案4】:

      如果您的预期输出是单行,您可以简单地从输出中删除所有换行符。将管道传输到 tr 实用程序或 Perl(如果愿意)并不少见:

      wc -l < log.txt | tr -d '\n'
      
      wc -l < log.txt | perl -pe 'chomp'
      

      您还可以使用命令替换来删除尾随的换行符:

      echo -n "$(wc -l < log.txt)"
      
      printf "%s" "$(wc -l < log.txt)"
      

      如果您的预期输出可能包含多行,您需要做出另一个决定:

      如果要从文件末尾删除多个换行符,请再次使用 cmd 替换:

      printf "%s" "$(< log.txt)"
      

      如果您想从文件中严格删除最后一个换行符,请使用 Perl:

      perl -pe 'chomp if eof' log.txt
      

      请注意,如果您确定要删除尾随换行符,则可以使用 GNU coreutils 中的head 来选择除最后一个字节之外的所有内容。这应该很快:

      head -c -1 log.txt
      

      此外,为了完整起见,您可以使用cat 和“显示全部”标志-A 快速检查文件中的换行符(或其他特殊)字符的位置。美元符号字符将指示每一行的结尾:

      cat -A log.txt
      

      【讨论】:

      • 这会从输出中删除所有换行符,而不仅仅是标题要求的尾随换行符。
      • @CodyA.Ray:你必须同意,这个问题描述了一个特定的命令,它只会产生一行输出。但是,我已经更新了我的答案以适应更一般的情况。 HTH。
      • 如果把空头期权换成多头期权会更好。长选项示教和功能,例如tr --delete '\n'.
      • 我也做过| tr -d '\r'
      • 我赞成head -c ... 版本——因为我可以现在 将命令提供到剪贴板并保留格式,但最后一个\n。例如:alias clip="head -c -1 | xclip -selection clipboard",不要太破旧。现在,当您使用管道 ls -l | clip ... 所有精彩的输出都将发送到 X-Server clipboard,而没有终止 \n。因此...我可以将其粘贴到我的下一个命令中,就这样。非常感谢!
      【解决方案5】:

      如果您想只删除最后一个换行符,请通过管道:

      sed -z '$ s/\n$//'
      

      如果分隔符通过-z 设置为NULsed 将不会在流的末尾添加\0,而创建 POSIX 文本文件(定义为以 \n 结尾),它总是会输出一个最终的\n 而没有-z

      例如:

      $ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
      foo
      bartender
      

      为了证明没有 NUL 添加:

      $ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
      00000000: 666f 6f0a 6261 72                        foo.bar
      

      删除多个尾随换行符,请通过管道:

      sed -Ez '$ s/\n+$//'
      

      【讨论】:

      • 我想这是一个 GNU 扩展,Mac sed 不提供 -z
      • 你可以在 mac 上安装 gnu 版本的 sed,gsed 并使用它,doing what it says here
      • 有人能解释一下sed表达式开头的$ 是做什么的吗?
      【解决方案6】:

      Bash variable substitution 中也直接支持删除空格:

      testvar=$(wc -l < log.txt)
      trailing_space_removed=${testvar%%[[:space:]]}
      leading_space_removed=${testvar##[[:space:]]}
      

      【讨论】:

      • 你也可以使用trailing_linebreak_removed=${testvar%?}
      • 请注意,如果您使用命令替换,那么您无需执行任何操作来删除尾随换行符。 Bash 已经将其作为命令替换的一部分:gnu.org/software/bash/manual/html_node/…
      【解决方案7】:

      一种方式:

      wc -l < log.txt | xargs echo -n
      

      【讨论】:

      • 更好:echo -n `wc -l log.txt`
      • 为什么在反引号中执行命令比使用管道更好?
      • 这些不仅会删除尾随的换行符,还会将任何连续的空格(更准确地说,由IFS 定义)压缩到一个空格。示例:echo "a b" | xargs echo -necho -n $(echo "a b")。对于用例来说,这可能是也可能不是问题。
      • 更糟糕的是,如果输出以-e 开头,它将被解释为echo 的选项。使用printf '%s' 总是更安全。
      • xargs 在我的系统上非常慢(我怀疑它也在其他系统上),所以printf '%s' $(wc -l log.txt) 可能更快,因为printf 通常是内置的(也因为有没有信息重定向)。永远不要使用反引号,它们在较新的 POSIX 版本中已被弃用,并且有许多缺点。
      【解决方案8】:

      printf 已经为你裁剪了尾随换行符:

      $ printf '%s' $(wc -l < log.txt)
      

      详情:

      • printf 将打印您的内容以代替 %s 字符串占位符。
      • 如果您不告诉它打印换行符 (%s\n),它就不会。

      【讨论】:

      • 如果您在命令周围加上双引号,例如"$(command)",内部换行符将被保留——并且只有 尾随 换行符将被删除。 shell 在这里完成了所有工作——printf 只是将命令替换结果返回到stdout 的一种方式。
      • 这里不是 printf 剥离新行,而是使用 $( ) 构造的 shell。这是证据:printf "%s" "$(perl -e 'print "\n"')"
      • 同样,值得注意的是生成的命令行可能会变得太长。
      • 这是@nobar 建议的便捷解决方案:$ printf '%s' "$(wc -l &lt; log.txt)"
      【解决方案9】:

      如果将其输出分配给变量,bash 会自动去除空格:

      linecount=`wc -l < log.txt`
      

      【讨论】:

      • 确切地说,尾随换行符被删除。删除它们的是命令替换,而不是变量赋值。
      • 我在 Cygwin bash 中看到使用 $(cmd /c echo %VAR%) 时没有删除尾随空格。在这种情况下,我不得不使用 ${var%%[[:space:]]}。
      • 注意:不是变量赋值,而是去掉换行符的表达式展开。
      猜你喜欢
      • 2023-03-15
      • 2022-01-05
      相关资源
      最近更新 更多