0

Consider the following nonsense array:

# KIND[ID]=NAME
MONKEYS[1]="Oo Oo"
MONKEYS[2]="Aa Aa"
MONKEYS[3]="Ba Nana"
LIONS[5]="Mister Mufasa"
LIONS[7]="Cocoa Puff"
LIONS[8]="Lala Leo"
TIGERS[13]="Ben Gal"
TIGERS[15]="Tee Eye Double Guh Err"
TIGERS[22]="Oh Esex Diez Punto Cuatro"

With a given KIND and ID, I'm attempting to build a string that resembles $NAME[$ID] to get the associated name.

When explicitly stating an array name, the command behaves as expected echo "${LIONS[5]}"=>"Mister Mufasa"). However, whenever a variable is used, the shell responds with the given character in the string.

$LIONS[5] => 'e' # The fifth letter in "Mister Mufasa"

In other cases, I can't find a way to control interpolation to get the NAME

KIND="LIONS"
ID="5"

# Attempt to return value of `LIONS` when `KIND=LIONS`
echo $"${KIND}"; echo "\$${KIND}" #=> "$LIONS"
echo "$${KIND}" #=> "57800{KIND}" Interpolates "$$"
echo "\$\${KIND}"; "\$\${KIND}" #=> "$${KIND}"

I found the following works albeit "ugly"...

eval echo `echo \\$${KIND}`

However when introducing the ID things break once again:

eval echo `echo \\$${KIND}[$ID]`
#> title:5: no matches found: $LIONS[5]
#> no matches found: $LIONS[5]

I feel like I'm missing something very simple. I have a hunch I'm forgetting to escape something, but I'm not quite sure what.

Also, what "less redundant" alternatives to eval echo `echo... or eval echo `print... exist?

3
  • possible duplicate of Bash indirect array addressing? Commented May 15, 2012 at 7:55
  • Please see BashFAQ/006. You should probably use Bash 4 and its associative arrays or another language with more powerful data structures. Commented May 15, 2012 at 14:14
  • @l0b0 I actually am employing a more portable indirect reference above since using "\$$var, ... preceded by an eval (and sometimes an echo)" is the classic indirect reference. The syntax that Gordon introduced below ${!VAR} seems to be Bash specific. @Dennis, the FAQ utilizes the same method as well. Commented May 15, 2012 at 16:43

1 Answer 1

2

In bash, use indirect addressing:

REF="$KIND[$ID]" # Sets REF to "LIONS[5]"
echo "${!REF}"   # Prints "Mister Mufasa"

EDIT: In zsh, use nested expansion instead:

echo "${(P)${KIND}[ID]}"
Sign up to request clarification or add additional context in comments.

3 Comments

Perfect for Bash, but not much else. The latest ZSH performs an expansion to echo "${REF="$KIND[$ID]"}" which throws back an 's' once again.
I gave up on finding something universal. It seems expansions are handled very differently across shells.
Yes, portability tends to be difficult (/impossible) for anything outside the POSIX standard. And since neither arrays nor indirect expansion are in the standard...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.