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

hex*_*ide 163 bash newline line-breaks

当我在Bash中执行命令(或具体地说wc -l < log.txt)时,输出后面包含一个换行符.我怎么摆脱它?

Ste*_*eve 214

如果您的预期输出是单行,则只需从输出中删除所有换行符即可.管道到'tr'实用程序或Perl(如果首选)是不常见的:

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

wc -l < log.txt | perl -pe 'chomp'
Run Code Online (Sandbox Code Playgroud)

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

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

printf "%s" "$(wc -l < log.txt)"
Run Code Online (Sandbox Code Playgroud)

请注意,我不同意OP决定选择接受的答案.我相信应尽可能避免使用'xargs'.是的,这是一个很酷的玩具.不,你不需要它.


如果您的预期输出可能包含多行,则您还有另一个决定:

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

printf "%s" "$(< log.txt)"
Run Code Online (Sandbox Code Playgroud)

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

perl -pe 'chomp if eof' log.txt
Run Code Online (Sandbox Code Playgroud)

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

head -c -1 log.txt
Run Code Online (Sandbox Code Playgroud)

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

cat -A log.txt
Run Code Online (Sandbox Code Playgroud)

  • 我也做了`| tr -d '\r'` (3认同)
  • 如果短期权被长期期权所取代,那将会更好.长期选项教导以及功能,例如`tr --delete'\n'`. (2认同)
  • 我的赞成票是对 `head -c ... ` 版本 -- 因为我现在可以将命令输入剪贴板并保留格式,但对于最后一个 `\n`。例如:`alias clip="head -c -1 | xclip -selection clipboard"`,不要太简陋。现在当你用管道`ls -l | clip` ...所有这些美妙的输出都进入了 X-Server 的 `clipboard` 而没有终止的 `\n`。因此......我可以将其粘贴到我的下一个命令中,_就这样_。非常感谢! (2认同)

Sat*_*tya 87

单程:

wc -l < log.txt | xargs echo -n
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*ale 19

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

sed -z '$ s/\n$//'
Run Code Online (Sandbox Code Playgroud)

sed\0如果分隔符设置为NULvia -z,则不会在流的结尾添加 a ,而要创建 POSIX 文本文件(定义为以 a 结尾\n),它将始终输出最终\n不带-z.

例如:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender
Run Code Online (Sandbox Code Playgroud)

并证明没有NUL添加:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar
Run Code Online (Sandbox Code Playgroud)

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

sed -Ez '$ s/\n+$//'
Run Code Online (Sandbox Code Playgroud)

  • 我想这是一个 GNU 扩展,Mac `sed` 不提供 `-z`。 (7认同)

And*_*nov 12

Bash变量替换中也直接支持空格删除:

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

  • 您还可以使用 `trailing_linebreak_removed=${testvar%?}` (3认同)

nne*_*neo 9

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

linecount=`wc -l < log.txt`
Run Code Online (Sandbox Code Playgroud)

  • 准确地说,删除了追踪新行.它是删除它们的命令替换,而不是变量赋值. (9认同)
  • 我在Cygwin bash中看到使用$(cmd/c echo%VAR%)时未删除的尾随空格.在这种情况下,我必须使用$ {var %% [[:space:]]}. (2认同)

zer*_*2cx 9

printf已为您裁剪尾随换行符:

$ printf '%s' $(wc -l < log.txt)
Run Code Online (Sandbox Code Playgroud)

详情:

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

  • 如果在命令周围加上双引号,如"$(command)"`,则会保留内部换行符 - 只删除*尾随*换行符.shell正在这里完成所有工作 - "printf"只是将命令替换结果引回到`stdout`的一种方法. (7认同)
  • 不是 printf 在此处剥离了新行,而是 shell 使用 `$()` 构造来执行此操作。这是证明:`printf "%s" "$(perl -e 'print "\n"')"` (3认同)

Lou*_*uis 9

添加这个供我参考,比其他任何东西都重要^_^

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

VAR=$'helloworld\n'

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

echo "${CLEANED}"
Run Code Online (Sandbox Code Playgroud)


小智 5

如果要在不带行尾的情况下以Bash打印任何内容的输出,请使用-n开关将其回显。

如果您已经将其包含在变量中,则以裁剪的换行符回显它:

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar
Run Code Online (Sandbox Code Playgroud)

或者,您也可以一行完成,而不是:

    $ echo -n $(wc -l < log.txt)
Run Code Online (Sandbox Code Playgroud)

  • 该变量在技术上是不必要的。`echo -n $(wc -l &lt;​​ log.txt)` 具有相同的效果。 (4认同)