简体   繁体   English

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

[英]copy the value of the variable rather than reference bash script

I am a bit new to the bash scripting. 我对bash脚本有点陌生。 So please bear with me. 所以,请忍受我。 I am trying to create a table and assign the values in for loop like this: 我试图创建一个表,并在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"]}

The output for this is: 输出为:

0
1
2
the first value is 2

While my expected output is: 虽然我的预期输出是:

0
1
2
the first value is 0

So basically the variable's reference is being assigned to this rather than the value. 因此,基本上将变量的引用分配给该变量而不是值。 How to solve this? 如何解决呢?

My bash version: 我的bash版本:

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

TIA TIA

bash 3.2 only has indexed arrays, so packageMap[$package] only works as intended if $package is an integer, not an arbitrary string. bash 3.2仅具有索引数组,因此,如果$package是整数而不是任意字符串,则packageMap[$package]packageMap[$package]预期工作。

(What you are observing is $package being evaluated in an arithmetic context, where foo , bar , and foobar are recursively expanded until you get an integer value. Undefined variables expand to 0, so packageMap[foo] is equivalent to packageMap[0] .) (您观察到的是$package在算术上下文中求值,其中foobarfoobar递归扩展,直到获得整数值为止。未定义的变量扩展为0,所以packageMap[foo]等同于packageMap[0] 。)

If you were using bash 4 or later, you could use an associative array: 如果您使用的是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
}

Given that i is the same as the index of each element of packages , you could also write 鉴于ipackages中每个元素的索引相同,您还可以编写

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

instead of explicitly incrementing i . 而不是显式增加i

As chep says, there are no associative arrays in bash 3. That said, if you don't mind wasting a bit of CPU, you can use functions to similar effect: 正如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")"

The ${!array[@]} construct expands to the set of indices for the array, which for a normally non-associative array consist of incrementing integers starting at 0. But array members can be removed without the indices being renumbered (ie unset packages[1] ), so it's important to be able to refer to actual indices rather than assuming they're sequential with for loop that simply counts. ${!array[@]}构造扩展为数组的索引集,对于通常不相关的数组,该数组由从0开始的递增整数组成。但是可以删除数组成员而无需重新编号索引(即未unset packages[1]索引) unset packages[1] ),因此重要的是能够引用实际索引,而不是假设它们与简单计数的for循环是连续的。

And I note that you're using Darwin. 而且我注意到您正在使用达尔文。 Remember that you really need it, you can install bash 4 using Homebrew or MacPorts . 请记住,您确实需要它,可以使用HomebrewMacPorts安装bash 4。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM