I'm sure it is relatively simple, I just don't know how to do it.

set `iostat`

I want to something like echo ${$myvar} which i want interpreted as ${$myvar} -> ${6} -> value

  • 8
    The technical term is variable indirection.
    – Thor
    Jun 24, 2012 at 13:18

4 Answers 4


You can do this with eval, built-in to many fine shells, including ksh:

set $(iostat)
eval "echo \${$myvar}"

The trick is to double-quote the string you feed to eval so that $myvar gets substituted with "6", and to backslash the outer dollar-sign, so that eval gets a string "$6".

I got "%user" for the output, but I tried it on a multi-processor RHEL machine.

  • 6
    You are officially the Supreme Exalted Grand Master of the week b/c that even works on the unfathomably awful ksh (really pdksh) in OpenBSD 5.4. If you want to set var vv to the value of the var whose name is in the var vn, just do vv=$( eval "echo \$$vn" ). Thanks a ton!
    – execNext
    Apr 5, 2014 at 0:07

Indirect variable reference

Modern advanced shells have a method to reference the value of a variable whose name is stored in another variable. Unfortunately the method differs between ksh, bash and zsh.

In mksh ≥R39b, you can make myvar a nameref:

typeset -n myvar=6
echo "$myvar"

This doesn't work in ATT ksh93 because it doesn't support namerefs to positional parameters. In the case where you have a variable containing a variable name, you can use this method.

typeset -n myvar=foo
echo "$myvar"  # prints bar

In bash ≥2.0, you can write

echo "${!myvar}"

In zsh, you can write

echo ${(P)myvar}

In older shells, including ksh88 and pdksh, your only recourse when you have a variable containing another variable name and want to use the value of this variable eval, as explained by Bruce Ediger. This solution works in any Bourne/POSIX shell.

eval "value=\${$myvar}"
echo "$value"

Using an array

This is the best method here: it's simpler and more portable.

For your use case, in any shell with arrays (all ksh variants, bash ≥2.0, zsh), you can assign to an array variable and take the element you wish. Beware that ksh and bash arrays start numbering at 0, but zsh starts at 1 unless you issue setopt ksh_arrays or emulate ksh.

set -A iostat -- $(iostat)
echo "${iostat[5]}"

If you want to copy the positional parameters to an array variable a:

set -A a -- "$@"

In ksh93, mksh ≥R39b, bash ≥2.0 and zsh, you can use the array assignment syntax:

echo "${iostat[5]}"
  • Wow, your 'Bourne/POSIX' solution also works in OpenBSD 5.4's ksh/pdksh. To apply it to the example in my comment to Bruce Ediger's answer above, just do eval "vv=\${$vn}". Merci beaucoup, kind sir.
    – execNext
    Apr 5, 2014 at 0:23
  • echo ${(P)myvar} is p a var, like p=1?
    – Timo
    Jun 1, 2021 at 13:05
  • 1
    @Timo I guess you're asking about (P)? It's a parameter expansion flag. Jun 1, 2021 at 13:10
  • I have code: s_cust_plugin='s|custom/plugins/'; echo "b=$0\na=${((P)s_cust_plugin$1/|)b}\necho $a[2] loaded". Result:add_zsh_plugin:2: error in flags -- I want to echo the name of script that I invoke with exec zsh after adding this code to the script.
    – Timo
    Jun 1, 2021 at 13:15
  • 1
    @Timo What you wrote is syntactically incorrect and I can't figure out what you intended to do. This is too complicated for a comment. Ask a new question. Jun 1, 2021 at 13:29

As indicated by Gilles (who provided the bash part of the answer), also not invalidating Bruce Ediger’s (on how to do it portably with eval), here’s how to do it with nameref in recent mksh (and AT&T ksh93, except – as @Gilles commented – namerefs cannot refer to positional parameters in AT&T ksh, only to named parameters):

set -- $(iostat)
nameref myvar=6
echo $myvar

Added the -- after set for improved resistence, too.

  • As of ksh 93u, namerefs can't reference positional parameters (typeset: 6: invalid variable name). Feb 27, 2014 at 14:35

Another use of arrays

Haven't used either ksh or any variant for some time, so I'm not sure if ksh(or bash) has a similar capability. My primary shell is zsh. I use arrays when handling output from commands like iostat because they produce multiple lines, and not all lines are the same format/length.

#! /bin/zsh
IOStatOutput=("${(@f)$(iostat)}") # Produces one element per line

The above also bypasses the use of positional parameters. Now, if you want to generate, say, an array of devices:

for Element in {7..${#IOStatOutput}} # Devices listed in elements 7 thru the last
    DevList+=( ${${=IOStatOutput[Element]}[1]} )

I find smaller chunks much easier to handle. You may or may not need to use indirect variable reference, depending on your code. Knowing how it works is still a good thing to know. I use it myself.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .