我想用管道调用一个函数,并将所有stdin读入一个变量.
我读到这样做的正确方法是read,或者或者read -r或read -a.但是,我在实践中遇到了很多问题(尤其是多行字符串).
最后我决定
function example () {
local input=$(cat)
...
}
Run Code Online (Sandbox Code Playgroud)
cat根据我运行的测试,我发现与以下方法相比,使用速度非常慢:
local input="$(< /dev/stdin)"
Run Code Online (Sandbox Code Playgroud)
如果有人想知道,<这只是输入重定向。来自 bash-hackers wiki(新链接直至修复):
例如,当内部命令只是输入重定向,而没有其他命令时
Run Code Online (Sandbox Code Playgroud)$( <FILE ) # or ` <FILE `然后 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中找到。
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)