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 即可。在函數中添加第二個參數,這將告訴函數從哪個數字開始或添加到結果中,並在缺少第二個參數的情況下添加合理的預設值。或將索引循環為史普拉蒂克先生建議。

相關內容