我想用管道调用一个函数,并将所有的stdin读入一个变量。我读到正确的方法是使用read,或者read -r或read -a。然而,我在实践中遇到了很多问题(尤其是多行字符串)。最后我决定
read
read -r
read -a
function example () { local input=$(cat) ... }
gdx19jrr1#
input=$(cat)是捕获标准输入的一种非常好的方法。需要注意的是,命令替换会删除所有尾随的换行符,因此如果您希望确保也捕获这些换行符,则需要确保最后读取除换行符之外的内容。
input=$(cat)
input=$(cat; echo x) input=${input%x} # Strip the trailing x
bash 4或更高版本中的另一个选项是使用readarray命令,该命令将用每行标准输入填充数组,每个元素一行,然后可以根据需要将其连接回单个变量。
bash
readarray
readarray foo printf -v foo "%s" "${foo[@]}"
gtlvzcf82#
根据我运行的测试,我发现使用cat与下面的方法相比非常慢:
cat
local input="$(< /dev/stdin)"
如果有人想知道,<只是输入重定向。来自bash-hackers wiki(*new link until fixed *):当内部命令只是一个输入重定向,而没有其他内容时,例如
<
$( <FILE ) # or ` <FILE `
然后Bash尝试读取给定的文件,并在给定的命令是cat FILE时执行操作。
cat FILE
就这种方法的可移植性而言,你可能会在你的整个linux用户生涯中,从来没有使用过没有/dev/stdin的linux系统,但是如果你想满足这个愿望,这里有一个question on Unix Stackexchange,它质疑直接访问/dev/{stdin,stdout,stderr}和朋友的可移植性。我在使用linux * 容器 *(例如使用docker或buildah构建的容器)时遇到的另一件事是,有些情况下/dev/stdin甚至/dev/stdout在容器中不可用。我还不能确定是什么原因造成的。
/dev/stdin
/dev/{stdin,stdout,stderr}
/dev/stdout
p4rjhz4m3#
在SO上有一些重叠/非常相似的问题。我在这里使用read内置函数回答了这个问题:https://stackoverflow.com/a/58452863/3220983然而,在我的回答中,我只关心一行**。
**cat方法的一个有争议的缺点是需要生成一个子shell。**否则,这是一个很好的方法。这可能是处理多行处理的最简单的方法,就像这里特别询问的那样。
我认为read方法更快/更高效,如果你试图链接很多命令,或者反复遍历一个列表来调用一个函数。
3条答案
按热度按时间gdx19jrr1#
input=$(cat)
是捕获标准输入的一种非常好的方法。需要注意的是,命令替换会删除所有尾随的换行符,因此如果您希望确保也捕获这些换行符,则需要确保最后读取除换行符之外的内容。bash
4或更高版本中的另一个选项是使用readarray
命令,该命令将用每行标准输入填充数组,每个元素一行,然后可以根据需要将其连接回单个变量。gtlvzcf82#
根据我运行的测试,我发现使用
cat
与下面的方法相比非常慢:如果有人想知道,
<
只是输入重定向。来自bash-hackers wiki(*new link until fixed *):当内部命令只是一个输入重定向,而没有其他内容时,例如
然后Bash尝试读取给定的文件,并在给定的命令是
cat FILE
时执行操作。关于可移植性的说明
就这种方法的可移植性而言,你可能会在你的整个linux用户生涯中,从来没有使用过没有
/dev/stdin
的linux系统,但是如果你想满足这个愿望,这里有一个question on Unix Stackexchange,它质疑直接访问/dev/{stdin,stdout,stderr}
和朋友的可移植性。我在使用linux * 容器 *(例如使用docker或buildah构建的容器)时遇到的另一件事是,有些情况下
/dev/stdin
甚至/dev/stdout
在容器中不可用。我还不能确定是什么原因造成的。p4rjhz4m3#
在SO上有一些重叠/非常相似的问题。我在这里使用
read
内置函数回答了这个问题:https://stackoverflow.com/a/58452863/3220983
然而,在我的回答中,我只关心一行**。
**
cat
方法的一个有争议的缺点是需要生成一个子shell。**否则,这是一个很好的方法。这可能是处理多行处理的最简单的方法,就像这里特别询问的那样。我认为
read
方法更快/更高效,如果你试图链接很多命令,或者反复遍历一个列表来调用一个函数。