如何删除bash中的尾随换行符?

Fli*_*imm 10 bash shell-script text-processing newlines

我正在寻找行为类似于 Perl 的chomp. 我正在寻找一个简单地打印其输入的命令,如果它是换行符,则减去最后一个字符:

$ printf "one\ntwo\n" | COMMAND_IM_LOOKING_FOR ; echo " done"
one
two done
$ printf "one\ntwo" | COMMAND_IM_LOOKING_FOR ; echo " done"
one
two done
Run Code Online (Sandbox Code Playgroud)

(Bash 和 Zsh 中的命令替换会删除所有尾随的新行,但我正在寻找最多删除一个尾随新行的东西。)

cuo*_*glm 16

您可以perl不使用chomp

$ printf "one\ntwo\n" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done

$ printf "one\ntwo" | perl -0 -pe 's/\n\Z//'; echo " done"
one
two done
Run Code Online (Sandbox Code Playgroud)

但为什么不使用chomp它自己:

$ printf "one\ntwo\n" | perl -pe 'chomp if eof'; echo " done"
Run Code Online (Sandbox Code Playgroud)


Lat*_*SuD 10

这应该有效:

printf "one\ntwo\n" | awk 'NR>1{print PREV} {PREV=$0} END{printf("%s",$0)}' ; echo " done"
Run Code Online (Sandbox Code Playgroud)

脚本总是打印前一行而不是当前行,最后一行的处理方式不同。

它更详细地做什么:

  1. NR>1{print PREV} 打印上一行(第一次除外)。
  2. {PREV=$0}将当前行存储在PREV变量中。
  3. END{printf("%s",$0)} 最后,打印最后一行而不换行。

另请注意,这将在末尾删除最多一个空行(不支持删除"one\ntwo\n\n\n")。


Gil*_*il' 5

如果您想要完全等同于chomp,我想到的第一种方法是LatinSuD 已经发布awk 解决方案。我会添加一些其他的方法,这些方法没有实现,chomp但实现了一些chomp经常使用的常见任务。

当您将一些文本填充到变量中时,末尾的所有换行符都会被删除。所以所有这些命令都会产生相同的单行输出:

echo "$(printf 'one\ntwo') done"
echo "$(printf 'one\ntwo\n') done"
echo "$(printf 'one\ntwo\n\n') done"
echo "$(printf 'one\ntwo\n\n\n\n\n\n\n\n\n\n') done"
Run Code Online (Sandbox Code Playgroud)

如果您想将一些文本附加到文件或命令输出的最后一行,sed可以很方便。使用 GNU sed 和大多数其他现代实现,即使输入没有以换行符结尾¹,这也有效;但是,如果还没有换行符,这将不会添加换行符。

sed '$ s/$/ done/'
Run Code Online (Sandbox Code Playgroud)

¹但是,这不适用于所有 sed 实现:sed 是一种文本处理工具,并且非空且不以换行符结尾的文件不是文本文件。