zsh-users
 help / color / mirror / code / Atom feed
* Re: OPTARG not being set?
@ 1999-02-03  8:23 Bart Schaefer
  0 siblings, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 1999-02-03  8:23 UTC (permalink / raw)
  To: zsh-users; +Cc: Sweth Chandramouli

On Feb 3, 12:03am, Bart Schaefer wrote:
} Subject: Re: OPTARG not being set?
}
} 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}

One point of additional clarity:  As I said, the \$ is not converted to $
when the outer $(echo ...) is parsed; but $(echo ${bob}) is substituted
when the quoted string is parsed, which is how it becomes "echo \${joe}".
Then, although the backslash is then finally stripped, the $ becomes a
quoted character (because of appearing inside quotes), and is thus not
lexed as the start of a substitution when the string produced by the outer
$(echo ...) is finally executed.

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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: OPTARG not being set?
@ 1999-02-03 18:35 Sweth Chandramouli
  0 siblings, 0 replies; 7+ messages in thread
From: Sweth Chandramouli @ 1999-02-03 18:35 UTC (permalink / raw)
  To: zsh-users

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
<sweth@gwu.edu> / (202) 994 - 8521 (V) / (202) 994 - 0458 (F)
<a href="http://astaroth.nit.gwu.edu/~sweth/disc.html">*</a>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: OPTARG not being set?
@ 1999-02-03  8:03 Bart Schaefer
  0 siblings, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 1999-02-03  8:03 UTC (permalink / raw)
  To: Sweth Chandramouli, zsh-users

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

${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.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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

	${joe}

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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: OPTARG not being set?
@ 1999-02-03  7:38 Sven Wischnowsky
  0 siblings, 0 replies; 7+ messages in thread
From: Sven Wischnowsky @ 1999-02-03  7:38 UTC (permalink / raw)
  To: zsh-users


Sweth Chandramouli wrote:

> (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
> (astaroth)~6: echo ${(e)bob}
> joe
> (astaroth)~7: echo "echo \${$(echo ${bob})}"
> echo ${joe}
> (astaroth)~8: `echo "echo \${$(echo ${bob})}"`
> joe
> (astaroth)~9: echo ${ZSH_VERSION}
> 3.1.5
> 
> 	i would think that #5 should print hello world,
> that #6 would explicitly cause parameter expansion and
> print hello world, and that #8 would evaluate the results
> of #7, which would be the same as typing #3, and would
> thus print hello world.

For standard 3.1.5 the syntax with an embedded ${...} inside a ${...}
is only useful if the outer ${...} contains some flags or other
modifying stuff. It will then work on the word(s) produced by the
inner${...}.
The (e) flag means the the string resulting from the whole ${...} will 
(at the end) be subject to another expansion (so if you had
bob=\$joe, it would work).
#8 irritates me, especially since:

  % $(echo "echo \${$(echo ${bob})}")

yields ${b}. This almost certainly caused by some weird quoting rules, 
which may even be documented.
Anyway, you should use eval for this:

  % eval echo "\$$bob"

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: OPTARG not being set?
@ 1999-02-03  3:56 Sweth Chandramouli
  0 siblings, 0 replies; 7+ messages in thread
From: Sweth Chandramouli @ 1999-02-03  3:56 UTC (permalink / raw)
  To: zsh-users

On Tue, Feb 02, 1999 at 09:52:45AM +0100, Bernd Eggink wrote:
> Options with arguments are denoted as "p:". ":p" has a different
> meaning; see "man zshbuiltins".

	ah yes, the revenge of the glaringly obvious typo.

	my next question, then, is why the following occurs:

(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
(astaroth)~6: echo ${(e)bob}
joe
(astaroth)~7: echo "echo \${$(echo ${bob})}"
echo ${joe}
(astaroth)~8: `echo "echo \${$(echo ${bob})}"`
joe
(astaroth)~9: echo ${ZSH_VERSION}
3.1.5

	i would think that #5 should print hello world,
that #6 would explicitly cause parameter expansion and
print hello world, and that #8 would evaluate the results
of #7, which would be the same as typing #3, and would
thus print hello world.

	-- sweth.

-- 
Sweth Chandramouli
IS Coordinator, The George Washington University
<sweth@gwu.edu> / (202) 994 - 8521 (V) / (202) 994 - 0458 (F)
<a href="http://astaroth.nit.gwu.edu/~sweth/disc.html">*</a>



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: OPTARG not being set?
@ 1999-02-02  8:52 Bernd Eggink
  0 siblings, 0 replies; 7+ messages in thread
From: Bernd Eggink @ 1999-02-02  8:52 UTC (permalink / raw)
  To: zsh-users

Sweth Chandramouli wrote:

...
>         this is the start of the function:
> 
> unset USER_SPECIFIED_PATH;
> while getopts ":p" CMD_LINE_OPT ; do
>    case ${CMD_LINE_OPT} in
>       p  ) USER_SPECIFIED_PATH=${OPTARG};;
>       \? ) print "unknown option \"-${OPTARG}\""
>            print 'usage: '
>            print 'addpath [-p PSEUDO_ARRAY] first_item:second_item:...:nth_item'
>            return 1
>    esac;
> done;
> 
>         after this loop finishes, however, USER_SPECIFIED_PATH is still
> null.  i've put some echo statements in the case clause for option p,
> which confirm that OPTARG is never being set, even though CMD_LINE_OPT
> is matching 'p'.  does anyone have any idea why?

Options with arguments are denoted as "p:". ":p" has a different
meaning; see "man zshbuiltins".

Regards,
	Bernd
-- 
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

* OPTARG not being set?
@ 1999-02-02  5:54 Sweth Chandramouli
  0 siblings, 0 replies; 7+ messages in thread
From: Sweth Chandramouli @ 1999-02-02  5:54 UTC (permalink / raw)
  To: ZSH Users

	i have a function that i use to set any PATH-style variables,
which checks each token to be added to the pseudo-array to see if it
is already present, and also to see if it actually exists as a 
directory, before adding it.  by default, it takes its input and tries
to add it to PATH; since i originally wrote it for the korn shell
many years ago, before i knew about getopts, i had it use an ugly
if-then clause to accept a command-line argument of '-p VARIABLE'
so that it could be used to set other variables (like MANPATH,
LD_LIBRARY_PATH, etc.).  i've finally gotten around to cleaning it
up, and as part of that, am trying to use getopts to set the
name of the variable to be set; i'm missing something, however,
because now it doesn't work.

	this is the start of the function:

unset USER_SPECIFIED_PATH;
while getopts ":p" CMD_LINE_OPT ; do
   case ${CMD_LINE_OPT} in
      p  ) USER_SPECIFIED_PATH=${OPTARG};;
      \? ) print "unknown option \"-${OPTARG}\""
           print 'usage: '
           print 'addpath [-p PSEUDO_ARRAY] first_item:second_item:...:nth_item'
           return 1
   esac;
done;

	after this loop finishes, however, USER_SPECIFIED_PATH is still
null.  i've put some echo statements in the case clause for option p,
which confirm that OPTARG is never being set, even though CMD_LINE_OPT
is matching 'p'.  does anyone have any idea why?

	thanks,
	sweth, who is still interested in maybe working on a proposal
for the zsh book, but is for now just cleaning up and commenting all
of his startup files to put on a web page.

-- 
Sweth Chandramouli
IS Coordinator, The George Washington University
<sweth@gwu.edu> / (202) 994 - 8521 (V) / (202) 994 - 0458 (F)
<a href="http://astaroth.nit.gwu.edu/~sweth/disc.html">*</a>



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1999-02-03 18:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-03  8:23 OPTARG not being set? Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
1999-02-03 18:35 Sweth Chandramouli
1999-02-03  8:03 Bart Schaefer
1999-02-03  7:38 Sven Wischnowsky
1999-02-03  3:56 Sweth Chandramouli
1999-02-02  8:52 Bernd Eggink
1999-02-02  5:54 Sweth Chandramouli

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).