[英]How to pass an associative array as argument to a function in Bash?
如何將關聯數組作為參數傳遞給 function? 這在 Bash 中是否可行?
下面的代碼沒有按預期工作:
function iterateArray
{
local ADATA="${@}" # associative array
for key in "${!ADATA[@]}"
do
echo "key - ${key}"
echo "value: ${ADATA[$key]}"
done
}
像普通的 arrays 一樣將關聯的 arrays 傳遞給 function 不起作用:
iterateArray "$A_DATA"
或者
iterateArray "$A_DATA[@]"
上周我遇到了完全相同的問題,並考慮了很長時間。
似乎關聯數組無法序列化或復制。 關聯數組有一個很好的Bash FAQ條目,其中詳細解釋了它們 。 最后一部分為我提供了以下對我有用的想法:
function print_array {
# eval string into a new associative array
eval "declare -A func_assoc_array="${1#*=}
# proof that array was successfully created
declare -p func_assoc_array
}
# declare an associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# show associative array definition
declare -p assoc_array
# pass associative array in string form to function
print_array "$(declare -p assoc_array)"
基於Florian Feldhaus的解決方案:
# Bash 4+ only
function printAssocArray # ( assocArrayName )
{
var=$(declare -p "$1")
eval "declare -A _arr="${var#*=}
for k in "${!_arr[@]}"; do
echo "$k: ${_arr[$k]}"
done
}
declare -A conf
conf[pou]=789
conf[mail]="ab\npo"
conf[doo]=456
printAssocArray "conf"
輸出將是:
doo: 456
pou: 789
mail: ab\npo
更新,以完全回答問題,這是我庫中的一小部分:
shopt -s expand_aliases
alias array.getbyref='e="$( declare -p ${1} )"; eval "declare -A E=${e#*=}"'
alias array.foreach='array.keys ${1}; for key in "${KEYS[@]}"'
function array.print {
array.getbyref
array.foreach
do
echo "$key: ${E[$key]}"
done
}
function array.keys {
array.getbyref
KEYS=(${!E[@]})
}
# Example usage:
declare -A A=([one]=1 [two]=2 [three]=3)
array.print A
這是我之前工作的發展,我將在下面進行介紹。
@ffeldhaus-很好的響應,我接受了它並運行了它:
t()
{
e="$( declare -p $1 )"
eval "declare -A E=${e#*=}"
declare -p E
}
declare -A A='([a]="1" [b]="2" [c]="3" )'
echo -n original declaration:; declare -p A
echo -n running function tst:
t A
# Output:
# original declaration:declare -A A='([a]="1" [b]="2" [c]="3" )'
# running function tst:declare -A E='([a]="1" [b]="2" [c]="3" )'
如果您使用的是Bash 4.3或更高版本, 最干凈的方法是按名稱傳遞關聯數組,然后使用帶有local -n
的名稱引用在函數內部訪問它。 例如:
function foo {
local -n data_ref=$1
echo ${data_ref[a]} ${data_ref[b]}
}
declare -A data
data[a]="Fred Flintstone"
data[b]="Barney Rubble"
foo data
您不必使用_ref
后綴; 這就是我在這里選擇的 只要引用與原始變量名稱不同即可,您可以調用該引用(否則將收到“循環名稱引用”錯誤)。
您只能按名稱傳遞關聯數組。
更好地(更有效)按名稱傳遞常規數組。
喲:
#!/bin/bash
declare -A dict
dict=(
[ke]="va"
[ys]="lu"
[ye]="es"
)
fun() {
for i in $@; do
echo $i
done
}
fun ${dict[@]} # || ${dict[key]} || ${!dict[@] || ${dict[$1]}
Z
這是另一種方法:您可以在將關聯數組傳遞給 function 時手動序列化它,然后將其反序列化回 function 內的新關聯數組:
這是來自我的eRCaGuy_hello_world 存儲庫的完整、可運行的示例:
array_pass_as_bash_parameter_2_associative.sh :
# Print an associative array using manual serialization/deserialization
# Usage:
# # General form:
# print_associative_array array_length array_keys array_values
#
# # Example:
# # length indices (keys) values
# print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
print_associative_array() {
i=1
# read 1st argument, the array length
array_len="${@:$i:1}"
((i++))
# read all key:value pairs into a new associative array
declare -A array
for (( i_key="$i"; i_key<$(($i + "$array_len")); i_key++ )); do
i_value=$(($i_key + $array_len))
key="${@:$i_key:1}"
value="${@:$i_value:1}"
array["$key"]="$value"
done
# print the array by iterating through all of the keys now
for key in "${!array[@]}"; do
value="${array["$key"]}"
echo " $key: $value"
done
}
# Let's create and load up an associative array and print it
declare -A array1
array1["a"]="cat"
array1["b"]="dog"
array1["c"]="mouse"
# length indices (keys) values
print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
樣品 output:
a: cat
b: dog
c: mouse
對於名為print_associative_array
的給定 function ,以下是一般形式:
# general form
print_associative_array array_length array_keys array_values
對於名為array1
的數組,以下是如何獲取數組長度、索引(鍵)和值:
"${#array1[@]}"
"${!array1[@]}"
"${array1[@]}"
因此,對print_associative_array
的示例調用如下所示:
# example call
# length indices (keys) values
print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
將數組的長度放在首位是必不可少的,因為它允許我們在傳入的序列化數組到達print_associative_array
function 時解析所有傳入 arguments 的魔術@
數組中的數組。
要解析@
數組,我們將使用數組切片,其描述如下(此片段是從我的答案復制粘貼在這里):
# array slicing basic format 1: grab a certain length starting at a certain
# index
echo "${@:2:5}"
# │ │
# │ └────> slice length
# └──────> slice starting index (zero-based)
# Print an associative array by passing the array by reference
# Usage:
# # General form:
# print_associative_array2 array
# # Example
# print_associative_array2 array1
print_associative_array2() {
# declare a local **reference variable** (hence `-n`) named `array_reference`
# which is a reference to the value stored in the first parameter
# passed in
local -n array_reference="$1"
# print the array by iterating through all of the keys now
for key in "${!array_reference[@]}"; do
value="${array_reference["$key"]}"
echo " $key: $value"
done
}
echo 'print_associative_array2 array1'
print_associative_array2 array1
echo ""
echo "OR (same thing--quotes don't matter in this case):"
echo 'print_associative_array2 "array1"'
print_associative_array2 "array1"
樣品 output:
print_associative_array2 array1
a: cat
b: dog
c: mouse
OR (same thing--quotes don't matter in this case):
print_associative_array2 "array1"
a: cat
b: dog
c: mouse
man bash
pages state 的declare
和local
-n
屬性“不能應用於數組變量”,但它可以? 這是我今天使用eval echo ...
進行間接處理的一種解決方案:
print_assoc_array() {
local arr_keys="\${!$1[@]}" # \$ means we only substitute the $1
local arr_val="\${$1[\"\$k\"]}"
for k in $(eval echo $arr_keys); do #use eval echo to do the next substitution
printf "%s: %s\n" "$k" "$(eval echo $arr_val)"
done
}
declare -A my_arr
my_arr[abc]="123"
my_arr[def]="456"
print_assoc_array my_arr
在bash 4.3上的輸出:
def: 456
abc: 123
出色的。 @Todd Lehman描述的簡單解決方案解決了我的關聯數組傳遞問題。 我必須將 3 個參數,一個 integer、一個關聯數組和一個索引數組傳遞給 function。
前段時間我讀到,由於 bash 中的 arrays 不是一流實體, 因此 arrays 無法作為 ZDBC11C1554E1B671D71D9CZ 傳遞給函數 Z77769 函數。 顯然,這畢竟不是全部真相。 我剛剛實現了一個解決方案,其中 function 處理這些參數,就像這樣......
function serve_quiz_question() {
local index="$1"; shift
local -n answers_ref=$1; shift
local questions=( "$@" )
current_question="${questions[$index]}"
echo "current_question: $current_question"
#...
current_answer="${answers_ref[$current_question]}"
echo "current_answer: $current_answer"
}
declare -A answers
answers[braveheart]="scotland"
answers[mr robot]="new york"
answers[tron]="vancouver"
answers[devs]="california"
# integers would actually be assigned to index \
# by iterating over a random sequence, not shown here.
index=2
declare -a questions=( "braveheart" "devs" "mr robot" "tron" )
serve_quiz_question "$index" answers "${questions[@]}"
隨着局部變量的分配,我不得不shift
位置參數移開,以便以( "$@" )
將剩下的內容分配給索引問題數組。
需要索引數組,以便我們可以可靠地迭代所有問題,無論是隨機還是有序序列。 關聯 arrays 不是有序數據結構,因此不適用於任何類型的可預測迭代。
Output:
current_question: mr robot
current_answer: new york
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.