如何在不更改尾部换行符(如果有)的情况下在shell脚本中打印变量?

时间:2014-09-08 23:14:53

标签: shell printf echo newline sh

我有一个shell脚本,它从另一个shell脚本获取输入。流在stdin上传输。

我需要将stdin流的所有字节捕获到shell脚本中的单个变量。然后,对它执行一些操作,并通过stdout将其发回。

我遇到的问题是输入文件中有时会出现一个尾随的换行符,但有时却没有。如果没有,那么我不想添加一个。但是,如果有一个尾随换行符,我想保留它。

问题在于,无论我尝试什么,系统总是输出没有尾随换行符(如printf的情况)或者总是输出换行符(如{{1}的情况}})。

请告诉我一个进程的名称(不是echoecho),它只是简单地接受一个变量并逐字逐句地将其流出,逐字节地传递给stdout。我已经尝试了printf的所有可能选项,但它们都不能保留尾随换行符。

请注意我对printfprintf两者都不能做到这一点很简单的事情不感兴趣。除非你能通过unix平台向我展示一个可移植的方式来使用这些命令来做我所要求的事情,在这种情况下我会全神贯注:D

1 个答案:

答案 0 :(得分:1)

标准技巧是在命令替换中附加一个sentinel字符,然后将其删除。这样,哨兵前面的任何东西都被剥夺了。

$ x=$(printf "Newlines stripped\n\n\n")
$ echo "$x"
Newlines stripped
$ x=$(printf "Newlines preserved\n\n\n"; printf "X")
$ x=${x%X}
$ echo "$x"
Newlines preserved


$

您还可以在循环中使用read内置函数,一次将标准输入中的一行追加到变量中,从而避免出现删除换行符的命令替换问题。

while IFS= read -r line; do
    x="$x$line"
done

一旦您在输出中安全地保留了任何换行符,您可以删除最后一个(如果存在),然后将其添加回来。这样,如果字符串最初没有换行符,那么现在就可以了;如果它最后有一个或多个换行符,则表示您没有更改尾随换行符的数量。

x="${x%"
"}
"

由于echo本身会在输出中添加换行符,因此您可以使用printf打印变量的值。 %s格式字符串指示printf按字面解释其参数。

printf %s "$x"

echo的某些版本可能支持-n选项来取消附加换行符,但它不是完全可移植的。)