From: Deborah Ariel Pickett <debbiep@mail.csse.monash.edu.au>
To: zsh-users@sunsite.dk
Subject: Word splitting in zsh
Date: Fri, 9 Feb 2001 12:23:59 +1100 (EST) [thread overview]
Message-ID: <200102090123.MAA55479@bruce.csse.monash.edu.au> (raw)
Hiya,
I've come across this little problem in zsh when I run it under
setopt SHWORDSPLIT (not that this is something I normally do).
What it boils down to is that in constructs like ${variable-word}
(where "-" is any of the characters that can go in that place - e.g.,
"-", "+", "=") the shell doesn't seem to be honouring double quotes the
way the manpage says.
Here's the relevant sections in the manpage:
[...] (Parameters)
@ In double quotes, array elements are put into sepa-
rate words. E.g., "${(@)foo}" is equivalent to
"${foo[@]}" and "${(@)foo[1,2]}" is the same as
"$foo[1]" "$foo[2]".
[...] (Parameter expansion)
${name:+word}
If name is set and is non-null then substitute
word; otherwise substitute nothing.
[...]
Note that double quotes may appear around nested substitu-
tions, in which case only the part inside is treated as
quoted; for example, ${(f)"$(foo)"} quotes the result of
$(foo), but the flag `(f)' (see below) is applied using
the rules for unquoted substitutions. Note further that
quotes are themselves nested in this context; for example,
in "${(@f)"$(foo)"}", there are two sets of quotes, one
surrounding the whole expression, the other (redundant)
surrounding the $(foo) as before.
With these two bits together, the POSIX and Bourne shells can make a
generic "any number of arguments, including zero" by using the form
${1+"$@"} (i.e., if $1 is set, substitute "$@", otherwise substitute
nothing).
Trying that in zsh, I get this:
bruce ~ % echo $ZSH_VERSION
3.1.6
# (But this also applies in 3.1.9)
bruce ~ % setopt
alwaystoend
noappendhistory
autocd
noautomenu
autonamedirs
autopushd
autoresume
braceccl
noclobber
completeinword
correct
extendedglob
noflowcontrol
globdots
histexpiredupsfirst
histignoredups
histnostore
ignoreeof
interactive
nolistbeep
longlistjobs
monitor
numericglobsort
promptsubst
pushdignoredups
pushdminus
pushdsilent
pushdtohome
shinstdin
zle
bruce ~ % setopt shwordsplit
# Now splitting is done like in other shells.
bruce ~ args()
function >{
function >for x
function for >do
function for >echo "'$x'"
function for >done
function >}
bruce ~ % args "a1 a2 a3" b c
'a1 a2 a3'
'b'
'c'
# Ok, that's what we expected.
bruce ~ % args "$@"
# Acceptable, but Bourne sh would print a single blank entry here, since
# there's a pair of quotes.
bruce ~ % args ${1+"$@"}
# This is the Proper Bourne Shell way to do it.
bruce ~ % set "a1 a2 a3" b c
bruce ~ % args "$@"
'a1 a2 a3'
'b'
'c'
# Fine . . .
bruce ~ % args ${1+"$@"}
'a1'
'a2'
'a3'
'b'
'c'
# What?? The $@ was in quotes, why was "a1 a2 a3" split?
bruce ~ % bash --posix
# Let's try the same under a POSIX shell.
bash-2.03$ args()
> {
> for x
> do
> echo "'$x'"
> done
> }
bash-2.03$ set "a1 a2 a3" b c
bash-2.03$ args ${1+"$@"}
'a1 a2 a3'
'b'
'c'
# Here it does it the correct way.
So . . am I misunderstanding how double quotes are propagated through
${} constructs in zsh? Or is this a bona fide bug? Whatever the
answer, this is something that doesn't work the same as in the Bourne
shell. Should it?
The only hint of an answer comes in this section of the manpage:
1. Nested Substitution
If multiple nested ${...} forms are present, sub-
stitution is performed from the inside outwards.
At each level, the substitution takes account of
whether the current value is a scalar or an array,
whether the whole substitution is in double quotes,
and what flags are supplied to the current level of
substitution, just as if the nested substitution
were the outermost. The flags are not propagated
up to enclosing substitutions; the nested substitu-
tion will return either a scalar or an array as
determined by the flags, possibly adjusted for
quoting. All the following steps take place where
applicable at all levels of substitution. Note
that, unless the `(P)' flag is present, the flags
and any subscripts apply directly to the value of
the nested substitution; for example, the expansion
${${foo}} behaves exactly the same as ${foo}.
This makes some sense, since these produce different results:
bruce ~ % args "${@}"
'a1 a2 a3'
'b'
'c'
bruce ~ % args "${${@}}"
'a1 a2 a3 b c'
though I wonder if they ought to, since this disagrees with the last
sentence about ${${foo}} and ${foo}.
--
Debbie Pickett http://www.csse.monash.edu.au/~debbiep debbiep@csse.monash.edu.au
"Look at me; I will never pass for a perfect bride, or a perfect daughter. Can
it be I'm not meant to play this part? Now I see that if I were truly to be
myself, I would break my family's heart." - Reflection, _Mulan_
next reply other threads:[~2001-02-09 1:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-02-09 1:23 Deborah Ariel Pickett [this message]
2001-02-09 3:09 ` Bart Schaefer
2001-02-09 7:34 ` Andrej Borsenkow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200102090123.MAA55479@bruce.csse.monash.edu.au \
--to=debbiep@mail.csse.monash.edu.au \
--cc=zsh-users@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).