Linux bash:多变量赋值

Posted

技术标签:

【中文标题】Linux bash:多变量赋值【英文标题】:Linux bash: Multiple variable assignment 【发布时间】:2010-12-29 11:21:08 【问题描述】:

在 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 个陈述。

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

【问题讨论】:

【参考方案1】:

我想到的第一件事:

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

不出所料,输出是

1|2|3

【讨论】:

如果第一个变量包含空格,是否有办法让它工作? @Michael 使用read -d "\n" v1 v2 &lt;&lt;&lt;$(cmd) 效果很好。谢谢! @LeeNetherton,好点,虽然我不确定是否需要 echo 命令的返回状态:-) 我认为在编写答案时支持这种语法的 bash 不太常见(如在默认情况下安装),虽然我不是 100% 确定。 @MichaelKrelin-hacker 当然,echo 的返回状态毫无意义,但我使用这种技术从我确实关心返回状态的脚本中返回多个值。我想我会分享我的发现。 为了安全起见,您应该使用:read -r:do not allow backslashes to escape any characters【参考方案2】:

我想将值分配给一个数组。所以,扩展Michael Krelin's approach,我做到了:

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

产生:

2|4|6 

正如预期的那样。

【讨论】:

要将值放入数组中,已经有一个简单的解决方案,我在问题中提到:a=( $(echo 2 4 6) ) ; echo $a[0] $a[1] $a[2] 是的,我忽略了这一点。不过,我会争辩说,我的建议更适合分配更大的数组。 @soundray 你的解决方案使用扩展和一个herestring,bash就是我怀疑它在那种情况下会表现良好(但我没有检查)。 为了安全起见,您应该使用:read -r:do not allow backslashes to escape any characters【参考方案3】:

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

为了在我的脚本中分解用户输入的日期(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 个子外壳加上一个额外的 sed 进程,而只需在一行中完成所有这些:IFS=/ read -r m d y &lt; &lt;(echo 12/29/2009)【参考方案4】:

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

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

你也可以通过管道进入 read 命令,但是你必须在子 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 命令不会在子shell 中发生,因为大括号,这是因为您在管道的右侧有读取命令。你需要在当前的shell中运行read命令,你可以像read day month year &lt;&lt;&lt; `date "+%d %m %Y"` 否 -- read 发生,但是当管道的子外壳结束时,它读入的变量的范围超出了范围。 我的评论是关于为什么读取发生在子shell中的原因,我现在意识到我误读了你写的内容。我以为您的意思是创建了子shell,因为您在复合语句周围使用了花括号。但!你给出这个例子的原因是为了避免分叉,但 subshel​​l 也不会分叉吗? 第一个示例只需要一个 fork: 以便 bash 可以启动 date 命令。在第二个示例中,您在日期和子 shell 之间设置了一个管道。我认为如今的 bash 足够聪明,不会真正分叉到子外壳中,但我不确定。无论如何,它看起来就像它会的那样:)【参考方案5】:

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

MYVAR="something"

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

这一切似乎有点像事后证明,但无论如何都没有提到分配给变量列表的方法。

【讨论】:

是的,我知道。为了便于阅读,我只是在这里和那里添加了额外的空格 这确实是一个糟糕的动机:如果 ';' 是一个有效的论点怎么办?当我写ls ; cd 时,它仍然调用lscd,尽管有空格。如果我想列出名为;cd 的目录,我可以输入ls ';' cd

以上是关于Linux bash:多变量赋值的主要内容,如果未能解决你的问题,请参考以下文章

Linux Bash Shell 中变量的 5 个易错点

bash 脚本在变量赋值时崩溃

Linux自学笔记:bash基础特性及基础命令

bash中的间接变量赋值

case语句中的变量赋值(bash)[重复]

Bash:在一行中改进变量间接赋值