Bash:从输出中去除尾随换行符

Posted

技术标签:

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

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

【问题讨论】:

【参考方案1】:

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

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

VAR=$'helloworld\n'

CLEANED="$VAR%$'\n'"

echo "$CLEANED"

【讨论】:

【参考方案2】:

使用 awk:

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

说明:

    -v 为 ORS 赋值 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:]]。 注意:不是变量赋值,而是去掉换行符的表达式展开。

以上是关于Bash:从输出中去除尾随换行符的主要内容,如果未能解决你的问题,请参考以下文章

shell中的输入输出(bash shell 03)

从 fgets() 输入中删除尾随换行符

从 fgets() 输入中删除尾随换行符

jinja2如何删除尾随换行符

jinja2如何删除尾随换行符

如何阻止GCC从obj文件中的字符串文字中删除尾随换行符?