bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to do? Possible?


From: Bob Proulx
Subject: Re: How to do? Possible?
Date: Mon, 25 Jul 2011 21:18:35 -0600
User-agent: Mutt/1.5.21 (2010-09-15)

Dennis Williamson wrote:
> Linda Walsh wrote:
> > GLOBAL="hi there"
> > {foo=GLOBAL echo ${!foo}; }

Note that this tickles a problem since foo isn't set before $foo is
expanded.  Use this following with a semicolon instead:

  GLOBAL="hi there"
  {foo=$GLOBAL; echo ${!foo}; }

> You had a missing dollar sign.
>
> I'm assuming you meant:
> 
> GLOBAL="hi there"
> {foo=$GLOBAL echo ${!foo}; }

Er..  No.  There is a missing semicolon as described above and in
other messages in the thread but the dollar size is intended to be
excluded so that foo contains the string "GLOBAL" and ${!foo} will
indirect through it.

The magic is the ${!parameter} syntax.  If you look at the bash
documentation for ${parameter} you will find the following
documentation.  The second paragraph explains the '!' part and is the
part needed to understand the indirection.

       ${parameter}
              The value of parameter is substituted.  The braces are
              required when parameter is a positional parameter with
              more than one digit, or when parameter is followed by a
              character which is not to be interpreted as part of its
              name.

       If the first character of parameter is an exclamation point
       (!), a level of variable indirection is introduced.  Bash uses
       the value of the variable formed from the rest of parameter as
       the name of the variable; this variable is then expanded and
       that value is used in the rest of the substitution, rather than
       the value of parameter itself.  This is known as indirect
       expansion.  The exceptions to this are the expansions of
       ${!prefix*} and ${!name[@]} described below.  The exclamation
       point must immediately follow the left brace in order to
       introduce indirection.

And so as you can see from this ${!foo} expands the value of foo to be
the string "GLOBAL" and then continues using that as an indirection
and expands the value of $GLOBAL.  With echo ${!foo} it would be very
similar to saying 'eval echo \$$foo'.  It would dynamically indirect
through and pick up the value of GLOBAL.

You can tell the difference by changing the value of GLOBAL between
echo statements.

Static direct binding:

  #!/bin/bash
  GLOBAL="one"
  foo=$GLOBAL
  { echo ${foo}; }
  GLOBAL="two"
  ( echo ${foo} )

Emits:

  one
  one

Dynamic indirect binding:

  #!/bin/bash
  GLOBAL="one"
  foo=GLOBAL
  { echo ${!foo}; }
  GLOBAL="two"
  ( echo ${!foo} )

Emits:

  one
  two

And the difference between using {...} and (...) is back to the
original discussion of the thread that subshells have access to
copies of all parent variables including variables that were not
explicitly exported.

Hope that helps to clarify things.

Bob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]