重击:从输出中去除尾随的换行符


187

当我在Bash中执行命令时(或更具体而言,wc -l < log.txt),输出后会包含换行符。我该如何摆脱呢?

Answers:


249

如果您的预期输出是一行,则可以简单地从输出中删除所有换行符。管道传输到'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)"

请注意,我不同意OP选择接受答案的决定。我认为应该避免使用“ xargs”。是的,这是一个很酷的玩具。不,您在这里不需要它。


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

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

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

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

perl -pe 'chomp if eof' log.txt


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

head -c -1 log.txt

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

cat -A log.txt

这将从输出中剥离所有换行符,而不仅仅是标题要求的尾随换行符。
Cody A. Ray

@ CodyA.Ray:但是,您必须同意,该问题描述的是仅将产生单行输出的特定命令。但是,我已经更新了答案,以适应更一般的情况。HTH。
史蒂夫

3
如果用长期权代替短期权,那会更好。长选项教学和功能,如tr --delete '\n'
伊利亚·林恩

1
我也做了| tr -d '\r'
AlikElzin-kilaka '16

值得注意的是,如果文件很大,则cmd替换解决方案可能会导致超长行。
phk

88

单程:

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

24
更好:echo -n `wc -l log.txt`
Satya

9
为什么在反引号中执行命令比使用管道更好?
马修·申克尔

2
这些不仅会删除尾随的换行符,还将所有连续的空格(更确切地说,由定义IFS)都压缩到一个空格中。例如:echo "a b" | xargs echo -n; echo -n $(echo "a b")。对于用例而言,这可能是问题,也可能不是问题。
musiphil

14
更糟糕的是,如果输出以开头-e,它将被解释为的选项echo。使用它总是更安全printf '%s'
musiphil

1
xargs在我的系统上非常慢(而且我怀疑在其他系统上也是如此),因此printf '%s' $(wc -l log.txt)可能会更快,因为printf通常是内置的(也因为没有信息重定向)。切勿使用反引号,反引号已在较新的POSIX版本中弃用,并具有许多缺点。
yyny

13

Bash变量替换中还直接支持去除空格:

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

1
您还可以使用trailing_linebreak_removed=${testvar%?}
PairedPrototype,

请注意,如果使用命令替换,则无需执行任何操作即可删除尾随的换行符。巴什已经这样做,作为命令替换的一部分:gnu.org/software/bash/manual/html_node/...
迈克尔·伯尔

10

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

linecount=`wc -l < log.txt`

10
确切地说,尾随的换行符被删除。删除它们的是命令替换,而不是变量分配。
chepner 2012年

2
我已经在Cygwin bash中看到使用$(cmd / c echo%VAR%)时未删除尾随空格。在这种情况下,我不得不使用$ {var %% [[:space:]]}。
安德烈·塔拉诺夫

1
注意:除去换行符的不是变量赋值,而是表达式扩展。
Ciro Santilli郝海东冠状病六四事件法轮功

10

printf已经为您裁剪了结尾的换行符:

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

详情:

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

7
如果在这样的命令"$(command)"中用双引号引起来,则内部的换行符将被保留-仅尾随的换行符将被删除。Shell在这里完成了所有工作- printf只是将命令替换的结果引导回的一种方法stdout
nobar 2014年

2
不是在这里剥离新行的是printf,而是由shell进行$( )构造的。这是证据:printf "%s" "$(perl -e 'print "\n"')"
Flimm

同样,值得注意的是,结果命令行可能会变得太长。
phk

这是@nobar建议的便捷解决方案:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim

8

如果您只想删除最后一个换行符,请通过以下方式传递管道:

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

sed\0如果定界符设置为NULvia -z,则不会在流的末尾添加a ,而要创建POSIX文本文件(定义为以结尾\n),它将始终输出final \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
Spidey

5

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

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

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

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

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

2
该变量在技术上是不必要的。echo -n $(wc -l < log.txt)具有相同的效果。
chepner 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.