Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: OPTARG not being set?

On Feb 2, 10:56pm, Sweth Chandramouli wrote:
} Subject: Re: OPTARG not being set?
} (astaroth)~1: joe='hello world'
} (astaroth)~2: bob=joe
} (astaroth)~3: echo ${joe}
} hello world
} (astaroth)~4: echo ${bob}
} joe
} (astaroth)~5: echo ${${bob}}
} joe

} 	i would think that #5 should print hello world

Nope.  Nested ${...} constructs don't act like that in zsh; the doc says

    The value, if any, of the parameter NAME is substituted. [...]

    If a `${'...`}' type parameter expression or a `$('...`)' type command
    substitution is used in place of NAME above, it is expanded first and
    the result is used as if it were the value of NAME.
That last phrase is key: the result is not used as if it were a new name,
it's used as if it were (should say was) the _value_.  (This is, IMO, not
very intuitive -- had I been designing the syntax, I would have scrapped
the inner `$' and nested only the braces; but then nested parameter name
substitution would not parallel $(...) substitution inside ${...}, which
is a different potential source of confusion.)

Thus only the innermost NAME is actually looked up in the parameter table
(or command substituted, or whatever).  All the rest of the processing
specified by flags or modifiers in the outer braces is applied to the
resulting value string or array.  That's why ${(t)${bob}} doesn't work,
because a value doesn't have a type; only names have types (which are
instructions for interpreting the value).

What Sven's new (P) flag does is force the value to be interpreted as a
new name, the way the syntax misled you expect all along.  (Maybe the
(P) flag ought to be ($), as in ${($)${bob}}.  Or more likely not.)

} (astaroth)~6: echo ${(e)bob}
} joe

} that #6 would explicitly cause parameter expansion and print hello world

First, note that ${bob} substitutes to "joe".  ${(e)bob} is similar (but
not identical) to $(echo ${bob}).  What's $(echo joe)?  Why, it's still
just "joe".  To get the effect you expected, you have to do

	bob='$joe'		# Note ${bob} now substitutes $joe
	${(e)${bob}}		# Like $(echo $joe) --> hello world

} (astaroth)~7: echo "echo \${$(echo ${bob})}"
} echo ${joe}
} (astaroth)~8: `echo "echo \${$(echo ${bob})}"`
} joe

} and that #8 would evaluate the results
} of #7, which would be the same as typing #3, and would
} thus print hello world.

Ah, now we're getting into it.  When the `...` expression is parsed, \$
is converted into just $.  _Then_ the string "echo ${$(echo ${bob})}"
is parsed, and by the magic of ${$(...)}, resolves to "echo joe", which
is what finally gets eval'd.

If instead you said $(echo "echo \${$(echo ${bob})}"), then the \$ is not
converted into bare $, and the string becomes "echo \${joe}", and the
result of the whole expression is


which is still not what you wanted.  It's very tricky to get backslashes
to be removed exactly when you want them to, because of the interactions
among the various kinds of quoting.

Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Messages sorted by: Reverse Date, Date, Thread, Author