我有一个功能来显示所选元素的索引。我试图将参数传递给函数以将其用作数组名称。这有效:
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 即可。向函数添加第二个参数,这将告诉函数从哪个数字开始或添加到结果中,并在缺少第二个参数的情况下添加合理的默认值。或者将索引循环为斯普拉蒂克先生建议。