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 < 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
设置为NUL
,sed
将不会在流的末尾添加\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 扩展,Macsed
不提供 -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 -n
; echo -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 < log.txt)"
【参考方案9】:
如果将其输出分配给变量,bash
会自动去除空格:
linecount=`wc -l < log.txt`
【讨论】:
确切地说,尾随换行符被删除。删除它们的是命令替换,而不是变量赋值。 我在 Cygwin bash 中看到使用 $(cmd /c echo %VAR%) 时没有删除尾随空格。在这种情况下,我不得不使用 $var%%[[:space:]]。 注意:不是变量赋值,而是去掉换行符的表达式展开。以上是关于Bash:从输出中去除尾随换行符的主要内容,如果未能解决你的问题,请参考以下文章