Linux bash:多变量分配


121

Linux bash中确实存在类似于PHP中以下代码的内容:

list($var1, $var2, $var3) = function_that_returns_a_three_element_array() ;

也就是说,您在一个句子中为3个不同的变量分配了一个对应的值。

假设我有bash函数myBashFuntion,该函数会写入标准输出字符串“ qwert asdfg zxcvb”。是否可以做类似的事情:

(var1 var2 var3) = ( `myBashFuntion param1 param2` )

等号左边的部分当然不是有效的语法。我只是想解释我的要求。

但是,有效的方法如下:

array = ( `myBashFuntion param1 param2` )
echo ${array[0]} ${array[1]} ${array[2]}

但是索引数组的描述性不如普通变量名。
但是,我可以这样做:

var1 = ${array[0]} ; var2 = ${array[1]} ; var3 = ${array[2]}

但是,我还是希望避免另外3条语句。

我只是在寻找一种快捷方式语法。可能吗?

Answers:


222

我想到的第一件事:

read -r a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c"

毫不奇怪,输出是

1|2|3

4
如果第一个变量包含空格,是否有办法使它起作用?
Rucent88

7
@Michael使用read -d "\n" v1 v2 <<<$(cmd)完美。谢谢!
2014年

1
@LeeNetherton,很好,虽然我不确定是否需要echo命令的返回状态:-)我认为在编写答案时,支持这种语法的bash不太常见(默认情况下已安装),我不是100%肯定。
Michael Krelin-黑客

4
@ MichaelKrelin-hacker当然,的返回状态echo没有意义,但是我使用这种技术从我确实关心返回状态的脚本中返回多个值。我以为我会分享我的发现。
李·尼瑟顿

1
为了安全,你应该使用:read -rdo not allow backslashes to escape any characters
汤姆·黑尔

18

我想将值分配给数组。因此,扩展了Michael Krelin的方法,我做到了:

read a[{1..3}] <<< $(echo 2 4 6); echo "${a[1]}|${a[2]}|${a[3]}"

产生:

2|4|6 

如预期的那样。


2
要将值放入数组中,我已经在问题中提到了一个简单的解决方案:a=( $(echo 2 4 6) ) ; echo ${a[0]} ${a[1]} ${a[2]}
GetFree 2014年

是的,我忽略了这一点。不过,我会说我的建议更适合于分配更大的数组。
soundray

@soundray您的解决方案使用扩展和herestring,bash是它的功能,我怀疑它在那种情况下是否能很好地工作(但我没有检查)。
卡米洛·马丁

为了安全,你应该使用:read -rdo not allow backslashes to escape any characters
汤姆·黑尔

5

我认为这可能会有所帮助...

为了在脚本中分解用户输入的日期(mm / dd / yyyy),我将日,月和年存储到数组中,然后将值放入单独的变量中,如下所示:

DATE_ARRAY=(`echo $2 | sed -e 's/\// /g'`)
MONTH=(`echo ${DATE_ARRAY[0]}`)
DAY=(`echo ${DATE_ARRAY[1]}`)
YEAR=(`echo ${DATE_ARRAY[2]}`)

为什么不避免使用4个子shell加上额外的sed过程,而只需一行即可完成所有操作:IFS=/ read -r m d y < <(echo 12/29/2009)
阿米特·奈杜

5

有时您必须做一些时髦的事情。假设您要从命令中读取数据(例如,SDGuero的日期示例),但您要避免多次派生。

read month day year << DATE_COMMAND
 $(date "+%m %d %Y")
DATE_COMMAND
echo $month $day $year

您也可以通过管道读取命令,但是必须在子shell中使用变量:

day=n/a; month=n/a; year=n/a
date "+%d %m %Y" | { read day month year ; echo $day $month $year; }
echo $day $month $year

结果是...

13 08 2013
n/a n/a n/a

read由于括号,该命令不会在子外壳中发生,这是因为在管道的右侧有read命令。您需要read在当前shell中运行命令,您可以像这样操作read day month year <<< `date "+%d %m %Y"`
气动

否- read 发生这种情况,但是当管道的子外壳终止时,它读入的变量的范围超出了范围。
奥西斯

1
我的评论是关于为什么在子外壳中进行读取的原因,现在我意识到我误读了您编写的内容。我以为您的意思是创建了子外壳,因为您在复合语句周围使用了花括号。但!您给出该示例的原因是为了避免分叉,但是subshel​​l fork也不会吗?
气动装置

第一个示例恰好需要一个fork:以便bash可以启动date命令。在第二个示例中,您在date和您的子外壳程序之间建立了一条管道。我认为这些天的bash足够聪明,不能实际插入subshel​​l中,但是我不确定。无论如何,它看起来像是:)
Otheus

0

O'Reilly撰写的Bash Cookbook的第5章(一定程度上)讨论了变量赋值要求在'='周围没有空格的原因

MYVAR="something"

解释与区分命令名和变量名(其中“ =”可能是有效的参数)有关。

这似乎有点像事件发生后的理由,但是无论如何都没有提及分配变量列表的方法。


是的我知道。为了可读性,我只是在这里和那里添加了额外的空间
GetFree

确实,这是一个很差的动机:如果' ;'是有效的论点怎么办?当我写的ls ; cd时候lscd尽管有空格,它仍然会调用。如果要列出称为的目录;,则cd可以键入ls ';' cd
PieterNuyts
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.