I'm sure it is relatively simple, I just don't know how to do it.
#!/usr/bin/ksh
set `iostat`
myvar=6
I want to something like echo ${$myvar}
which i want interpreted as ${$myvar}
-> ${6}
-> value
I'm sure it is relatively simple, I just don't know how to do it.
#!/usr/bin/ksh
set `iostat`
myvar=6
I want to something like echo ${$myvar}
which i want interpreted as ${$myvar}
-> ${6}
-> value
You can do this with eval
, built-in to many fine shells, including ksh:
#!/usr/bin/ksh
set $(iostat)
myvar=6
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.
vv=$( eval "echo \$$vn" )
. Thanks a ton!
– execNext
Apr 05 '14 at 00:07
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.
foo=bar
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"
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:
iostat=($(iostat))
echo "${iostat[5]}"
eval "vv=\${$vn}"
. Merci beaucoup, kind sir.
– execNext
Apr 05 '14 at 00:23
(P)
? It's a parameter expansion flag.
– Gilles 'SO- stop being evil'
Jun 01 '21 at 13:10
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 01 '21 at 13:15
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):
#!/bin/mksh
set -- $(iostat)
nameref myvar=6
echo $myvar
Added the --
after set
for improved resistence, too.
typeset: 6: invalid variable name
).
– Gilles 'SO- stop being evil'
Feb 27 '14 at 14:35
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
do
DevList+=( ${${=IOStatOutput[Element]}[1]} )
done
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.