复制变量的值,而不是引用bash脚本

时间:2018-07-30 20:05:30

标签: bash shell

我对bash脚本有点陌生。所以,请忍受我。我正在尝试创建一个表,并像这样在for循环中分配值:

packages=("foo" "bar" "foobar")
packageMap=()
function test() {
    i=0;
    for package in "${packages[@]}"
    do
        echo $i
        packageMap[$package]=$i
        i=$(expr $i + 1)
    done
}

test
echo the first value is ${packageMap["foo"]}

此输出为:

0
1
2
the first value is 2

我的预期输出是:

0
1
2
the first value is 0

因此,基本上将变量的引用分配给它,而不是值。该如何解决?

我的bash版本:

GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)

TIA

2 个答案:

答案 0 :(得分:6)

bash 3.2仅具有索引数组,因此,packageMap[$package]仅在$package是整数而不是任意字符串的情况下才能正常工作。

(您观察到的是$package在算术上下文中求值,其中foobarfoobar递归扩展,直到获得整数值为止。未定义的变量扩展为0,因此packageMap[foo]等效于packageMap[0]。)

如果您使用的是bash 4或更高版本,则可以使用关联数组:

packages=("foo" "bar" "foobar")
declare -A packageMap
test () {
    i=0
    for package in "${packages[@]}"
    do
        echo $i
        packageMap[$package]=$i
        i=$(($i + 1))
    done
}

鉴于ipackages的每个元素的索引相同,您也可以编写

test () {
    for i in "${!packages[@]}"; do
        package=${packages[i]}
        packageMap[$package]=$i
    done
}

而不是显式增加i

答案 1 :(得分:0)

正如chep所说,bash 3中没有关联数组。也就是说,如果您不介意浪费一点CPU,则可以使用具有类似效果的函数:

#!/bin/bash

packages=("foo" "bar" "foobar")

function packagemap () {
    local i
    for i in "${!packages[@]}"; do
        [[ ${packages[$i]} = $1 ]] && echo "$i" && return
    done
    echo "unknown"
}

echo "the first value is $(packagemap "foo")"

${!array[@]}构造扩展为数组的索引集,对于通常不相关的数组,该索引集由从0开始的递增整数组成。但是可以删除数组成员而无需重新编号索引(即{ {1}}),因此能够引用 actual 索引而不是假定它们与简单计数的for循环是连续的很重要。

我注意到您正在使用达尔文。请记住,您确实需要它,可以使用HomebrewMacPorts安装bash 4。