bash:从参数到函数获取数组名称并保存索引

bash:从参数到函数获取数组名称并保存索引

我有一个功能来显示所选元素的索引。我试图将参数传递给函数以将其用作数组名称。这有效:

getIndex() {
arrname=$1[@]
b=("${!arrname}")
index=1; while ((index<${#b[@]})); do
    if [[ "${b[$index]}" = "$VALUE" ]]; then
        echo "index is $index"; return
    fi  
        ((index++)); done

}

但是我传递给该函数的名称的数组具有索引 1 作为第一个元素的索引(我需​​要它具有类似于行号的索引,从中我可以获取数组中的模式:

a=1
while read line; do
    if [[ $line =~ ^[0-9] ]]; then
        avg[$a]=`echo $line | awk '{print $6}'`
        ((a++));    
    fi

如果我运行 getIndex() 函数,则数组的第一个元素从索引 0 开始。

所以,问题是:有没有办法将参数中的数组名称传递给函数并保存数组索引?或者也许我只需要忘记它并在函数答案中添加+1。

答案1

您正在使用这种结构:

b=("${!arrname}")

这扩展了价值观的数组,创建一个新b[]数组bash 默认数组索引从 0 开始。要正确初始化数组的副本,您需要恢复索引(例如通过解析或eval-ing 的输出declare -p arrname

与其复制,更好的方法是扩展索引而不是值,并使用它们迭代数组。这种方法适用于稀疏或基于非零的标准数组(甚至 bash4 关联数组)。

问题(并不总是存在)是 正在!承担双重职责:它在间接中的使用${!name}与它在扩展数组索引中的使用不兼容${!arrname[@]},所以我们必须使用eval.

这是实现此功能的修改版本:

getIndex2() {
  local arrname=$1 iidx idxs index ival val
  printf -v iidx '"${!%s[@]}"' "$arrname"
  eval "idxs=($iidx)"
  for index in "${idxs[@]}"; do
    printf -v ival '${%s[%s]}' "$arrname" "$index"
    eval "val=$ival"
    if [[ "${val}" = "$VALUE" ]]; then
        echo "index is $index"; return   
    fi
  done
}

请注意使用printf -v var ...(bash-3.1+) 来尽量保持eval可读性。索引扩展为数组,这并不是绝对必要的,平面列表也可以。

也可以看看BashFAQ/006

答案2

Bash 中的数组是从零开始的。他们就是这样。也就是说,如果你知道数组总是由从 1 开始的数字索引,只需在结果中添加 +1 即可。向函数添加第二个参数,这将告诉函数从哪个数字开始或添加到结果中,并在缺少第二个参数的情况下添加合理的默认值。或者将索引循环为斯普拉蒂克先生建议。

相关内容