在bash函数中,如何将stdin放入变量中

Pau*_*gar 3 linux bash shell

我想用管道调用一个函数,并将所有stdin读入一个变量.

我读到这样做的正确方法是read,或者或者read -rread -a.但是,我在实践中遇到了很多问题(尤其是多行字符串).

最后我决定

function example () {
  local input=$(cat)
  ...
}
Run Code Online (Sandbox Code Playgroud)

这样做的惯用方法是什么?

sma*_*c89 9

cat根据我运行的测试,我发现与以下方法相比,使用速度非常慢:

local input="$(< /dev/stdin)"
Run Code Online (Sandbox Code Playgroud)

如果有人想知道,<这只是输入重定向。来自 bash-hackers wiki新链接直至修复):

例如,当内部命令只是输入重定向,而没有其他命令时

$( <FILE )
# or
` <FILE `
Run Code Online (Sandbox Code Playgroud)

然后 Bash 尝试读取给定的文件,并在给定的命令是 的情况下执行操作cat FILE


关于可移植性的备注

就这种方法的可移植性而言,您很可能会在您的整个 Linux 用户生涯中,永远不会使用没有 的 Linux 系统/dev/stdin,但如果您想满足这种渴望,这里有一个关于 Unix Stackexchange 的问题,其中质疑直接访问/dev/{stdin,stdout,stderr}和好友的可移植性。

在使用容器(例如使用 docker 或 buildah 构建的容器)时,我遇到的另一件事是,在某些情况下,容器内/dev/stdin甚至/dev/stdout不可用。我无法确定地说明是什么原因造成的,但我相信这个答案可以在https://unix.stackexchange.com/q/716438/264812中找到。


che*_*ner 6

input=$(cat)如果你真的需要,它是捕获标准输入的完美方式.需要注意的是,命令替换会删除所有尾随换行符,因此如果您想确保捕获这些换行符,则需要确保最后读取除换行符之外的其他内容.

input=$(cat; echo x)
input=${input%x}   # Strip the trailing x
Run Code Online (Sandbox Code Playgroud)

bash4或更高版本中的另一个选项是使用该readarray命令,该命令将使用每行标准输入填充数组,每个元素一行,如果需要,您可以将其连接回单个变量.

readarray foo
printf -v foo "%s" "${foo[@]}"
Run Code Online (Sandbox Code Playgroud)