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 <<<$(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 < <(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 <<< `date "+%d %m %Y"`
否 -- read
发生,但是当管道的子外壳结束时,它读入的变量的范围超出了范围。
我的评论是关于为什么读取发生在子shell中的原因,我现在意识到我误读了你写的内容。我以为您的意思是创建了子shell,因为您在复合语句周围使用了花括号。但!你给出这个例子的原因是为了避免分叉,但 subshell 也不会分叉吗?
第一个示例只需要一个 fork: 以便 bash 可以启动 date 命令。在第二个示例中,您在日期和子 shell 之间设置了一个管道。我认为如今的 bash 足够聪明,不会真正分叉到子外壳中,但我不确定。无论如何,它看起来就像它会的那样:)【参考方案5】:
O'Reilly 撰写的Bash Cookbook 第 5 章(在一定程度上)讨论了在变量赋值中要求“=”符号周围没有空格的原因
MYVAR="something"
解释与区分命令名称和变量名称有关(其中 '=' 可能是有效参数)。
这一切似乎有点像事后证明,但无论如何都没有提到分配给变量列表的方法。
【讨论】:
是的,我知道。为了便于阅读,我只是在这里和那里添加了额外的空格 这确实是一个糟糕的动机:如果 ';
' 是一个有效的论点怎么办?当我写ls ; cd
时,它仍然调用ls
和cd
,尽管有空格。如果我想列出名为;
和cd
的目录,我可以输入ls ';' cd
。以上是关于Linux bash:多变量赋值的主要内容,如果未能解决你的问题,请参考以下文章