我试图让bash处理来自stdin的数据,但没有运气。我的意思是以下工作都不做:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
我希望输出为test=hello world。我尝试在“$test”周围加上“”引号,但也不起作用。
问题是如何捕获命令的输出,以保存在变量中,以便稍后在脚本中使用。我可能会重复一些之前的答案,但我试着把我能想到的所有答案排列起来进行比较和评论,所以请容忍我。
直观的构造
echo test | read x
echo x=$x
在Korn shell中是有效的,因为ksh已经实现了管道系列中的最后一个命令是当前shell的一部分。前面的管道命令是子shell。相反,其他shell将所有管道命令定义为子shell,包括最后一个。
这正是我更喜欢ksh的原因。
但必须复制与其他shell, bash f.ex。,则必须使用另一种结构。
要捕获1个值,这个构造是可行的:
x=$(echo test)
echo x=$x
但这只能满足收集1个值以供以后使用的需求。
为了捕获更多的值,这个构造是有用的,在bash和ksh中工作:
read x y <<< $(echo test again)
echo x=$x y=$y
有一个变种,我注意到在bash工作,但不是在ksh:
read x y < <(echo test again)
echo x=$x y=$y
<<< $(…)是一个here-document变体,它提供了标准命令行的所有元处理。< <(…)是文件替换操作符的输入重定向。
我现在在所有脚本中都使用“<<< $(”,因为它似乎是shell变量之间最可移植的构造。我有一套工具,可以在任何Unix风格的作业中随身携带。
当然,有一个普遍可行但粗糙的解决方案:
command-1 | {command-2; echo "x=test; y=again" > file.tmp; chmod 700 file.tmp}
. ./file.tmp
rm file.tmp
echo x=$x y=$y