arrays - BASH:将 $1 评估为字符串以调用数组长度

标签 arrays bash function variables parameters

我在这里写了这个函数:我想这样运行它,选择“title”;

function choose {
    echo $1;
    randNum=$RANDOM
    let "numChoices=${#$1[@]}";
    let "num=$randNum%$numChoices";
    i=0;

    while [ $i -lt $numChoices ]; do
        if [ $i -eq $num ]; then
            echo ${$1[$i]};
            break;
        fi
        ((i++));
    done
}

运行时,我希望最终产品与此相同:(将所有 $1 替换为标题)

function choose {
    echo title;
    randNum=$RANDOM
    let "numChoices=${#title[@]}";
    let "num=$randNum%$numChoices";
    i=0;

    while [ $i -lt $numChoices ]; do
        if [ $i -eq $num ]; then
            echo ${title[$i]};
            break;
        fi
        ((i++));
    done
}

但是,我得到的只是这个错误:

notify.sh: line 67: numChoices=${#$1[@]}: bad substitution

经过大量文档搜索后,我无法很好地理解替换、指针和引用。有人可以提供一些见解并纠正我的语法吗?

最佳答案

如果您使用的是 bash 4.3,则可以使用 nameref 变量,如下所示:(我还更新了脚本的各个部分。)

choose() {
    echo $1
    # This makes theVar an alias ("nameref") to the variable whose name is in $1
    # Like any declare inside a function, it is implicitly local.
    declare -n theVar=$1
    local randNum=$RANDOM
    local numChoices=${#theVar[@]}
    local num=$(( randNum % numChoices ))
    local i

    for (( i=0; i < numChoices; ++i )); do
        if (( i == num )); then
            echo "${theVar[i]}"
            break;
        fi
    done
}

但是您可能没有 bash 4.3,因为它还不到一年的历史,而且大多数发行版对 bash 更新都非常保守。因此,您需要使用旧式间接语法 ${!name}。不幸的是,这对于数组引用来说很尴尬,因为您需要使 name 包含整个下标表达式。而且,更糟糕的是,据我所知,它根本不处理数组长度(或者,就此而言,标量长度)。您可以使用 eval 获取数组长度,但我对 eval 的普遍偏见导致了以下替代实现:

choose() {
    echo $1
    local randNum=$RANDOM
    # For the indirection, we need to construct the indexed name.
    local name=$1[@]
    # This hack makes varSize a row of dots with one dot per element.
    local varSize=$(printf ".%.0s" "${!name}")
    local numChoices=${#varSize}
    local num=$(( randNum % numChoices ))
    local i

    for (( i=0; i < numChoices; ++i )); do
        if (( i == num )); then
            # Again, we need to construct the complete indexed name.
            name=$1[$i]
            echo "${!name}";
            break;
        fi
    done
}

关于arrays - BASH:将 $1 评估为字符串以调用数组长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25468664/

相关文章:

python - Python 中的静态数组

arrays - 从 Modelica 中的字符串参数访问数组元素

linux - 无法读取 bash 脚本中的第二个参数

java - 从 Java 中的 bash 脚本丢失数据

python - matlab函数到python函数的转换

c++ - 从列表中删除回调函数?

java - 尝试使用数组实现循环队列时出现 ArrayIndexOutOfBoundsException

c - 将两个指针交换为指针

bash - 使用 ENV 变量或默认值定义 Makefile 变量

r - 将相同的参数传递给多个嵌套函数