From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Wed, 3 Feb 1999 13:35:37 -0500 From: Sweth Chandramouli To: zsh-users@math.gatech.edu Subject: Re: OPTARG not being set? Message-ID: <19990203133537.B11106@astaroth.nit.gwu.edu> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Mailing-List: 2073 On Wed, Feb 03, 1999 at 12:03:02AM -0800, Bart Schaefer wrote: > Nope. Nested ${...} constructs don't act like that in zsh; the doc says > > ${NAME} > 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. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ see below for my comments on the syntactic definition of a "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) actually, were is the correct usage there. (despite what some people claim, the subjunctive does exist in english.) [snip] > 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). is the difference between a name and a value semantic instead of syntactic, then? i would assume that the shell decides what is a value and what is a name by the context in which it is placed; based on the definitions given in the manpage, it seems that ${...} constructs definitionally interpret the first token inside the braces to be a name. after reading over the paragraph you quote above a few times, i can see how it can be interpreted to mean what you say it means, which is that nested uses of ${...} override the syntactic identification of the first token of all but the innermost ${...} as a name, but i don't think that that is immediately clear (not that my restating of it is any better to anyone but a logician). there are, i guess, three ways to possible make this more understandable: 1) come up with a better version of the paragraph you quoted, that at least states explicitly that the nesting causes an exception to the definitions given just before that paragraph. with the current terminology, however, i don't know if it can really be made that clear no matter how it is worked over, which leads to... 2) after i sent in my original question, i did a search on the zsh-workers archive, and noticed that you had done some work on this same topic, at least in standardizing use of terms like "expansion" and "substitution". i think that it would help a lot to do the same thing for terms like "name", "word", and value"; if that were to be done, then i think that this could just be explained in the definitions of the various ${...} constructs themselves, rather than in a footnote at the end. 3) i'm not a huge fan of "magic" values and exceptions (which is one of the reasons that i've never really gotten that into perl); the third solution, then, would be to make the behaviour of ${...} standard regardless of whether or not they are nested. this would break lots of existing scripts, i'm sure--which is probably why the (P) flag was added, which leads to... > 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.) is this added in a dev version? i can't find reference to it in the 3.1.5 docs. > } (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}). how so? according to the docs, (e) says to "[p]erform parameter expansion, command substitution, and arithmetic expansion on the result." i originally thought that this meant that ${(e)${bob}} would parse to ${(e)joe}, and then perform parameter expansion on ${joe}--something akin to `eval echo $(bob)`; when that didn't work, i thought that maybe it implicitly assumed that the token following it was a parameter to be expanded before the ${...} param expansion took place, which is why i tried the version you quoted. from what you describe, it appears that (e) just does a command substitution on an echo of the value of the name passed to it. when would this be useful? >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 to do this dynamically (i.e. to get this effect when you don't know ahead of time that joe is name of the parameter to be expanded), however, you need to do something like bob="${${param_whose_value_is_joe}}", which is the original situation that caused me to start trying to figure all of this out. > } (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 > > ${joe} which led me to try `eval echo \${$(echo $bob)}', which does work: it parses to `eval echo \${joe}', strips off the \, and evals `echo ${joe}'. what i had originally been using, however, was `eval echo \${${bob}}'; the entire point of this exercise was to try to get rid of the eval. what is the difference between grave-accent command substitution, $(...) command substitution, and eval's pseudo-command substitution? it looks like grave accents strip meta-char escapes, do param expansion, and then evaluate, while $(...) just does param expansion and then evaluates, and eval does param expansion, strips meta-char escapes, and then evaluates. is that the case? are there any other differences? -- sweth. -- Sweth Chandramouli IS Coordinator, The George Washington University / (202) 994 - 8521 (V) / (202) 994 - 0458 (F) *