LDP/LDP/guide/docbook/abs-guide/ind-ref.sh

80 lines
2.2 KiB
Bash

#!/bin/bash
# ind-ref.sh: Indirect variable referencing.
# Accessing the contents of the contents of a variable.
# First, let's fool around a little.
var=23
echo "\$var = $var" # $var = 23
# So far, everything as expected. But ...
echo "\$\$var = $$var" # $$var = 4570var
# Not useful ...
# \$\$ expanded to PID of the script
# -- refer to the entry on the $$ variable --
#+ and "var" is echoed as plain text.
# (Thank you, Jakob Bohm, for pointing this out.)
echo "\\\$\$var = \$$var" # \$$var = $23
# As expected. The first $ is escaped and pasted on to
#+ the value of var ($var = 23 ).
# Meaningful, but still not useful.
# Now, let's start over and do it the right way.
# ============================================== #
a=letter_of_alphabet # Variable "a" holds the name of another variable.
letter_of_alphabet=z
echo
# Direct reference.
echo "a = $a" # a = letter_of_alphabet
# Indirect reference.
eval a=\$$a
# ^^^ Forcing an eval(uation), and ...
# ^ Escaping the first $ ...
# ------------------------------------------------------------------------
# The 'eval' forces an update of $a, sets it to the updated value of \$$a.
# So, we see why 'eval' so often shows up in indirect reference notation.
# ------------------------------------------------------------------------
echo "Now a = $a" # Now a = z
echo
# Now, let's try changing the second-order reference.
t=table_cell_3
table_cell_3=24
echo "\"table_cell_3\" = $table_cell_3" # "table_cell_3" = 24
echo -n "dereferenced \"t\" = "; eval echo \$$t # dereferenced "t" = 24
# In this simple case, the following also works (why?).
# eval t=\$$t; echo "\"t\" = $t"
echo
t=table_cell_3
NEW_VAL=387
table_cell_3=$NEW_VAL
echo "Changing value of \"table_cell_3\" to $NEW_VAL."
echo "\"table_cell_3\" now $table_cell_3"
echo -n "dereferenced \"t\" now "; eval echo \$$t
# "eval" takes the two arguments "echo" and "\$$t" (set equal to $table_cell_3)
echo
# (Thanks, Stephane Chazelas, for clearing up the above behavior.)
# A more straightforward method is the ${!t} notation, discussed in the
#+ "Bash, version 2" section.
# See also ex78.sh.
exit 0