如何在不删除任何尾随换行符的情况下将 stdin 捕获到变量?

如何在不删除任何尾随换行符的情况下将 stdin 捕获到变量?

在 shell 脚本中...

如何在不删除任何尾随换行符的情况下将 stdin 捕获到变量?

现在我已经尝试过:

var=`cat`
var=`tee`
var=$(tee)

在所有情况下,$var输入流都不会出现尾随换行符。谢谢。

另外:如果有输入中尾随换行符,则解决方案不得添加一个

根据已接受的答案进行更新:

我在代码中使用的最终解决方案如下:

function filter() {
    #do lots of sed operations
    #see https://github.com/gistya/expandr for full code
}

GIT_INPUT=`cat; echo x`
FILTERED_OUTPUT=$(printf '%s' "$GIT_INPUT" | filter)
FILTERED_OUTPUT=${FILTERED_OUTPUT%x}
printf '%s' "$FILTERED_OUTPUT"

如果您想查看完整代码,请参阅 github 页面扩展器,一点开源git 关键字扩展过滤器我出于信息安全目的而开发的 shell 脚本。根据制定的规则.gitattributes文件(可以是特定于分支的)和git配置, git 通过管道传输每个文件扩展器sh每当将其签入或签出存储库时都会执行 shell 脚本。 (这就是为什么保留任何尾随换行符或缺少换行符至关重要。)这可以让您清理敏感信息,并为测试、暂存和实时分支交换不同的环境特定值集。

答案1

在将值存储到变量中之前,尾随换行符将被删除。您可能想做类似的事情:

var=`cat; echo x`

并使用${var%x}代替$var.例如:

printf "%s" "${var%x}"

请注意,这解决了尾随换行问题,但不能解决空字节问题(如果标准输入不是文本),因为根据 POSIX 命令替换:

如果输出包含任何空字节,则行为未指定。

但 shell 实现可能会保留空字节。

答案2

您可以使用read内置函数来完成此操作:

$ IFS='' read -d '' -r foo < <(echo bar)

$ echo "<$foo>"
<bar
>

对于读取 STDIN 的脚本,只需:

IFS='' read -d '' -r foo

 

我不确定这会在什么 shell 中工作。但在 bash 和 zsh 中都可以正常工作。

答案3

你可以这样做:

input | { var=$(sed '$s/$/./'); var=${var%.}; }

$var无论如何,一旦你走出这个{ current shell ; }群体,你所做的一切都会消失。但它也可以像这样工作:

var=$(input | sed '$s/$/./'); var=${var%.}

答案4

我无法评价该解决方案的可移植性和稳健性,但它达到了我的预期:

var=$(</dev/stdin)

相关内容