2014-12-13 3 views
2

В этом очень упрощенном примере, мне нужно обратиться как ключ и значение массива элемента:Bash косвенной ссылкой на ассоциативный массив

declare -A writer 
writer[H.P.]=Lovecraft 
writer[Stephen]=King 
writer[Clive]=Barker 
writer[Jack]=Ketchum 

for i in ${!writer[@]} 
do 
    echo "$i ${writer[$i]}" 
done 

fullname() 
{ 
    pointer=$1[@] 
    for i in "${!pointer}" 
    do 
     echo "? $i" 
    done 
} 
fullname writer 

Функция должна отображать вывод в том же формате, как например, петли перед ним, и он должен получить либо имя массива, список ключей или значений, все из которых я пробовал, но безуспешно. Любые предложения приветствуются.

ответ

2
indir_keys() { 
    eval "echo \${!$1[@]}" 
} 

indir_val() { 
    eval "echo \${$1[$2]}" 
} 

fullname() 
{ 
    pointer=$1 
    for i in $(indir_keys $pointer) 
    do 
     echo "$i $(indir_val $pointer $i)" 
    done 
} 

Дает:

Jack Ketchum 
Clive Barker 
Stephen King 
H.P. Lovecraft 
+2

Это можно сделать более безопасным путем проверки того, что '$ 1' и' $ 2' являются * справедливыми * действительными идентификаторами, например, с помощью '[[$ 1 = ~ [A-Za-z _] [A-Za- z0-9 _] +]] || return'. – chepner

0

От Bash Reference Guide:

Позиционные параметры временно заменяются, когда функция оболочки выполняется (см Shell Functions).

Таким образом, вы можете сделать это:

fullname() 
{ 
    for first 
    do 
     echo "$first ${writer[$first]}" 
    done 
} 
fullname "${!writer[@]}" 
12

Поскольку Bash 4.3 declare имеет флаг -n определять ссылки (это слабо эквивалентно ссылки на C++). Этот флаг чрезвычайно упрощает вашу проблему здесь:

fullname() { 
    declare -nl pointer="$1" 
    for i in "${!pointer[@]}" 
    do 
     echo "${pointer[$i]} $i" 
    done 
} 

Это будет безопасно, если у вас возникли пробелы или забавные символы в ключах вашей хэш (в отличие от принятого ответа).

+0

Отлично, не знал об этой новой функции +1 это должно быть принято. – anubhava

Смежные вопросы