分配给变量时保留最后一个换行符的存在

分配给变量时保留最后一个换行符的存在

在 bash 中,当使用 捕获输出到变量中时$(...),会附加一个烦人的换行符。但是,我的输出有时以换行符结尾,有时则不然。我希望按原样捕获输出。

在我的实际问题中,字符串可能包含多行,但最后一行可能会也可能不会以换行符结束,并且应该保留此属性。

风格为Stack Exchange 上的这个答案,我的最小工作示例如下所示:

#!/bin/bash

newlinetest() {
    if [ "$1" = 'with' ]; then
        printf '%s\n' 'Text with newline'
    else
        printf '%s' 'Text without newline'
    fi
}

s="$(newlinetest with ; printf '%s' 'x')"
s="${s%?}"
printf '%s%s%s\n' '(' "${s}" ')'
s="$(newlinetest without ; printf '%s' 'x')"
s="${s%?}"
printf '%s%s%s\n' '(' "${s}" ')'

它做了它应该做的事情,但恕我直言,这看起来像是一个丑陋的黑客。还有其他优雅的方法来解决这个问题吗?也许涉及mapfileread?无需外部工具的解决方案将非常受欢迎。

答案1

实际上,命令替换会删除尾随换行符,但不会附加它们。但如果您echo稍后用来打印该变量,它会默认添加 1。

添加尾随x之类的确实有点黑客,但这可能是最简单的方法,并且适用于所有 shell。您可以使用echo x代替 来使其更短printf '%s' 'x'

既然你提到了read,你也可以使用这样的东西(在 Bash 中):

IFS= read -rd '' var < <(newlinetest with)

我将让您决定这是否比这更漂亮:

var=$(newlinetest with; echo x)
var=${var%x}

尽管两者之间存在潜在的性能差异。在第一个中,进程替换创建一个管道,该管道read读取一次一个字节以避免超出分隔符(这与这里无关,但 shell 不知道这一点。)命令替换将读取更大的块,因此对于大输出可能会更快。

相关内容