Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
${| cmd; } fails if set -u is active and REPLY is unset
- X-seq: zsh-workers 53258
- From: Lawrence Velázquez <larryv@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: ${| cmd; } fails if set -u is active and REPLY is unset
- Date: Wed, 18 Dec 2024 23:34:24 -0500
- Archived-at: <https://zsh.org/workers/53258>
- Feedback-id: iaa214773:Fastmail
- List-id: <zsh-workers.zsh.org>
Interesting edge case raised on bug-bash@xxxxxxx just now, regarding
the interaction between ${| cmd; } non-forking command substitutions
and set -u:
% cat /tmp/funsubs.sh
set -u
unset REPLY
(printf '<%s>\n' "$REPLY")
(printf '<%s>\n' "${| :; }")
(printf '<%s>\n' "${| unset REPLY; }")
% mksh /tmp/funsubs.sh
/tmp/funsubs.sh[3]: REPLY: parameter not set
<>
<>
% ~/src/bash/bash /tmp/funsubs.sh
/tmp/funsubs.sh: line 3: REPLY: unbound variable
<>
<>
% ~/src/zsh/zsh/Src/zsh /tmp/funsubs.sh
/tmp/funsubs.sh:3: REPLY: parameter not set
/tmp/funsubs.sh:4: : parameter not set
/tmp/funsubs.sh:5: : parameter not set
We currently disagree with mksh and bash on this, but we agree with
... ourselves ... with respect to ${{var} cmd; }:
% ~/src/zsh/zsh/Src/zsh -u <<\EOF
heredoc> unset foo
heredoc> : ${{foo} :; }
heredoc> EOF
zsh: foo: parameter not set
Do we want to remain diverged from mksh on ${| cmd; } to stay
consistent with our ${{var} cmd; }? (I don't know what bash is
going to do; the discussion hasn't really started yet.)
- If we retain our current ${| cmd; } behavior in native mode, we
might consider adopting the mksh behavior in ksh emulation mode.
- If we adopt the mksh ${| cmd; } behavior, users who do want
set -u to apply could always use ${{REPLY} cmd; }.
In any case, our error message is pretty confusing. "REPLY: parameter
not set" or something along the lines of "REPLY not set in non-forking
command substitution" would be nice, if possible.
--
vq
----- Original message -----
From: Zachary Santer <zsanter@xxxxxxxxx>
To: bug-bash <bug-bash@xxxxxxx>
Subject: ${| command; } funsub not setting REPLY does not error out with 'set -u' active
Date: Wednesday, December 18, 2024 9:39 PM
Was "waiting for process substitutions".
On Sat, Oct 12, 2024 at 10:09 AM Zachary Santer <zsanter@xxxxxxxxx> wrote:
>
> On Sun, Jul 14, 2024 at 8:40 PM Zachary Santer <zsanter@xxxxxxxxx> wrote:
> >
> > On Tue, Jul 9, 2024 at 2:37 PM Zachary Santer <zsanter@xxxxxxxxx> wrote:
> > >
> > > On the other hand, do funsubs give us the answer here?
> > >
> > > shopt -s lastpipe
> > > declare -a pid=()
> > > command-1 | tee >( command-2 ) ${ pid+=( "${!}" ); } >( command-3 ) ${
> > > pid+=( "${!}" ); } >( command-4 ) ${ pid+=( "${!}" ); }
> > > wait -- "${pid[@]}"
> >
> > This absolutely works, so there you go. When expanding multiple
> > process substitutions as arguments to a command, you can save the $!
> > resulting from each one by following it with an unquoted funsub that
> > does that work and doesn't expand to anything.
> >
> > > That looks obnoxious
> >
> > I don't mind how it looks. It works.
> >
> > > declare -a pid=()
> > > {
> > > commands
> > > } {fd[0]}< <( command-1 ) ${ pid+=( "${!}" ); } {fd[1]}< <( command-2
> > > ) ${ pid+=( "${!}" ); } {fd[2]}< <( command-3 ) ${ pid+=( "${!}" ); }
> > >
> > > Do things start breaking?
> >
> > Yeah, this doesn't work at all
>
> Even that can be made to work by simply removing the space between the
> process substitution and the following function substitution. Bash
> treats the whole amalgamation as one word.
If one wants to use funsubs that don't expand to anything as a
workaround like this, it might be more efficient to use the ${|
command; } form, as bash then isn't pointlessly redirecting stdout.
The manual describes 'set -u'/'set -o nounset' thusly:
Treat unset variables and parameters other than the special parameters
“@” and “*”, or array variables subscripted with “@” or “*”, as an
error when performing parameter expansion. If expansion is attempted
on an unset variable or parameter, the shell prints an error message,
and, if not interactive, exits with a non-zero status.
${| command; } isn't a parameter expansion, so not erroring out when
REPLY is not set within it wouldn't contradict the manual. However, to
me, it goes against the spirit of 'set -u', if you will.
On the other hand, I always use 'set -u', so if this were to become an
error, then I have to do REPLY='' within the ${| command; } funsub or
turn 'set -u' off and then back on again to use the funsub in this
way.
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: msys
Compiler: gcc
Compilation CFLAGS: -g -O2
uname output: MSYS_NT-10.0-19045 Zack2021HPPavilion
3.5.4-0bc1222b.x86_64 2024-12-05 09:27 UTC x86_64 Msys
Machine Type: x86_64-pc-msys
Bash Version: 5.3
Patch Level: 0
Release Status: beta
Git commit f223b24c4b.
In case that information is relevant.
$ set -u
$ unset REPLY
$ printf '%s\n' "${REPLY}"
bash: REPLY: unbound variable
$ printf '%s\n' "${| :; }"
$ printf '%s\n' "${| unset REPLY; }"
Just wanted to point this out.
Zack
Messages sorted by:
Reverse Date,
Date,
Thread,
Author