【问题标题】:Linux bash: Multiple variable assignmentLinux bash:多变量赋值
【发布时间】: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 个陈述。

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

【问题讨论】:

    标签: linux bash shell variable-assignment multiple-variable-return


    【解决方案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
    猜你喜欢
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    相关资源
    最近更新 更多