zsh-workers
 help / color / mirror / code / Atom feed
* Bug with assignments in some commands
@ 2021-01-18 15:32 Patrick Reader
  2021-01-18 16:34 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Patrick Reader @ 2021-01-18 15:32 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 734 bytes --]

Hi there,

I believe I have found a bug: in arithmetic $(( )) or $[ ] and variable 
expansions ${ } in some forms of command (pipelines, command 
substitutions, and inside here-documents and here-strings are the cases 
I know of so far), assignments to variables do not persist outside the 
command, almost as if it were in a subshell. I'm pretty sure this is a 
bug; if it's an intended behaviour, it's quite annoying and should be 
changed.

This does not occur in complex commands (if, for, while, etc.) except 
subshells.

This occurs on both zsh versions I have tested: 5.8 
(x86_64-pc-linux-gnu) and 5.6.2 (x86_64-redhat-linux-gnu).

Attached is a reproducible example, and the output of `set` and `set -o`.

Regards,

Patrick


[-- Attachment #2: assignment_bug.zsh --]
[-- Type: text/plain, Size: 780 bytes --]

# this increments x
x=1
echo "$((x++)), x is $x"
echo x is correct: $x

echo '========='

# but this doesn't change x outside the pipeline
x=1
echo "$((x++)), x is $x" | cat
echo x is still: $x

echo '========='

# same thing with non-arithmetic assignments ${name::=value}
# this works
x=1
echo "${x::=2}, x is $x"
echo x is correct: $x

echo '========='

# but this doesn't
x=1
echo "${x::=2}, x is $x" | cat
echo x is still: $x

echo '========='

x=1
echo $(echo "$((x++)), x is $x")
echo x is still: $x

echo '========='

x=1
<<<"$((x++)), x is $x"
echo x is still: $x

echo '========='

x=1
cat <<<"$((x++))"
echo x is still: $x

echo '========='

x=1
<<END
$((x++)), x is $x
END
echo x is still: $x

echo '========='

x=1
cat <<END
$((x++)), x is $x
END
echo x is still: $x

[-- Attachment #3: zsh_set.txt --]
[-- Type: text/plain, Size: 7123 bytes --]

!=0
'#'=0
'$'=16129
'*'=(  )
-=569X
0=REDACTED
'?'=0
@=(  )
ARGC=0
BASH_ENV=REDACTED
CDPATH=''
COLUMNS=0
CPUTYPE=x86_64
EGID=1000
EUID=1000
FIGNORE=''
FPATH=/usr/local/share/zsh/site-functions:/usr/share/zsh/site-functions:/usr/share/zsh/5.6.2/functions
FUNCNEST=500
GID=1000
HISTCHARS='!^#'
HISTCMD=0
HISTSIZE=30
HOME=/home/REDACTED
HOST=tio2
IFS=$' \t\n\C-@'
KEYBOARD_HACK=''
KEYTIMEOUT=40
LANG=en_US.UTF8
LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib
LD_PRELOAD=libstdbuf.so:REDACTED.so
LINENO=38
LINES=0
LISTMAX=100
LOGCHECK=60
LOGNAME=REDACTED
MACHTYPE=x86_64
MAILCHECK=60
MAILPATH=''
MANPATH=''
MODULE_PATH=/usr/lib64/zsh/5.6.2
NULLCMD=cat
OLDPWD=/home/REDACTED
OPTARG=''
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/local/bin:/usr/bin:/bin
PPID=16128
PROMPT=''
PROMPT2=''
PROMPT3='?# '
PROMPT4='+%N:%i> '
PS1=''
PS2=''
PS3='?# '
PS4='+%N:%i> '
PSVAR=''
PWD=/home/REDACTED
RANDOM=256
READNULLCMD=more
SAVEHIST=0
SECONDS=0
SHELL=/bin/bash
SHLVL=3
SPROMPT='zsh: correct '\''%R'\'' to '\''%r'\'' [nyae]? '
TIMEFMT='%J  %U user %S system %P cpu %*E total'
TMPPREFIX=/tmp/zsh
TRY_BLOCK_ERROR=-1
TRY_BLOCK_INTERRUPT=-1
TTY=''
TTYIDLE=-1
TZ=UTC
UID=1000
USER=REDACTED
USERNAME=REDACTED
VENDOR=redhat
WATCH=''
WATCHFMT='%n has %a %l from %m.'
WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>'
XDG_RUNTIME_DIR=/run/user/1000
ZSH_ARGZERO=REDACTED
ZSH_EVAL_CONTEXT=toplevel
ZSH_NAME=zsh
ZSH_PATCHLEVEL=zsh-5.6.2-0-g92bef88
ZSH_SCRIPT=REDACTED
ZSH_SUBSHELL=0
ZSH_VERSION=5.6.2
_=set
_STDBUF_E=0
_STDBUF_I=0
_STDBUF_O=0
aliases
argv=(  )
builtins
cdpath=(  )
commands
dirstack
dis_aliases
dis_builtins
dis_functions
dis_functions_source
dis_galiases
dis_patchars
dis_reswords
dis_saliases
fignore=(  )
fpath=( /usr/local/share/zsh/site-functions /usr/share/zsh/site-functions /usr/share/zsh/5.6.2/functions )
funcfiletrace
funcsourcetrace
funcstack
functions
functions_source
functrace
galiases
histchars='!^#'
history
historywords
jobdirs
jobstates
jobtexts
keymaps
mailpath=(  )
manpath=(  )
module_path=( /usr/lib64/zsh/5.6.2 )
modules
nameddirs
options
parameters
patchars
path=( /usr/local/bin /usr/bin /bin )
pipestatus=( 0 )
prompt=''
psvar=(  )
reswords
saliases
signals=( EXIT HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS ZERR DEBUG )
status=0
termcap
terminfo
userdirs
usergroups
watch=(  )
widgets
x=1
zsh_eval_context=( toplevel )
zsh_scheduled_events

noaliases             off
aliasfuncdef          off
allexport             off
noalwayslastprompt    off
alwaystoend           off
appendcreate          off
noappendhistory       off
autocd                off
autocontinue          off
noautolist            off
noautomenu            off
autonamedirs          off
noautoparamkeys       off
noautoparamslash      off
autopushd             off
noautoremoveslash     off
autoresume            off
nobadpattern          off
nobanghist            off
nobareglobqual        off
bashautolist          off
bashrematch           off
nobeep                off
nobgnice              off
braceccl              off
bsdecho               off
nocaseglob            off
nocasematch           off
cbases                off
cdablevars            off
chasedots             off
chaselinks            off
nocheckjobs           off
nocheckrunningjobs    off
noclobber             off
combiningchars        off
completealiases       off
completeinword        off
continueonerror       off
correct               off
correctall            off
cprecedences          off
cshjunkiehistory      off
cshjunkieloops        off
cshjunkiequotes       off
cshnullcmd            off
cshnullglob           off
nodebugbeforecmd      off
dvorak                off
emacs                 off
noequals              off
errexit               off
errreturn             off
noevallineno          off
noexec                off
extendedglob          off
extendedhistory       off
noflowcontrol         off
forcefloat            off
nofunctionargzero     off
noglob                off
noglobalexport        off
noglobalrcs           off
globassign            off
globcomplete          off
globdots              off
globstarshort         off
globsubst             off
nohashcmds            off
nohashdirs            on
hashexecutablesonly   off
nohashlistall         off
histallowclobber      off
nohistbeep            off
histexpiredupsfirst   off
histfcntllock         off
histfindnodups        off
histignorealldups     off
histignoredups        off
histignorespace       off
histlexwords          off
histnofunctions       off
histnostore           off
histreduceblanks      off
nohistsavebycopy      off
histsavenodups        off
histsubstpattern      off
histverify            off
nohup                 off
ignorebraces          off
ignoreclosebraces     off
ignoreeof             off
incappendhistory      off
incappendhistorytime  off
interactive           off
interactivecomments   off
ksharrays             off
kshautoload           off
kshglob               off
kshoptionprint        off
kshtypeset            off
kshzerosubscript      off
nolistambiguous       off
nolistbeep            off
listpacked            off
listrowsfirst         off
nolisttypes           off
localloops            off
localoptions          off
localpatterns         off
localtraps            off
login                 off
longlistjobs          off
magicequalsubst       off
mailwarning           off
markdirs              off
menucomplete          off
monitor               off
nomultibyte           off
nomultifuncdef        off
nomultios             off
nonomatch             off
nonotify              off
nullglob              off
numericglobsort       off
octalzeroes           off
overstrike            off
pathdirs              off
pathscript            off
pipefail              off
posixaliases          off
posixargzero          off
posixbuiltins         off
posixcd               off
posixidentifiers      off
posixjobs             off
posixstrings          off
posixtraps            off
printeightbit         off
printexitvalue        off
privileged            off
promptbang            off
nopromptcr            off
nopromptpercent       off
nopromptsp            off
promptsubst           off
pushdignoredups       off
pushdminus            off
pushdsilent           off
pushdtohome           off
rcexpandparam         off
rcquotes              off
norcs                 off
recexact              off
rematchpcre           off
restricted            off
rmstarsilent          off
rmstarwait            off
sharehistory          off
shfileexpansion       off
shglob                off
shinstdin             off
shnullcmd             off
shoptionletters       off
noshortloops          off
shwordsplit           off
singlecommand         off
singlelinezle         off
sourcetrace           off
sunkeyboardhack       off
transientrprompt      off
trapsasync            off
typesetsilent         off
nounset               off
verbose               off
vi                    off
warncreateglobal      off
warnnestedvar         off
xtrace                off
zle                   off

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

* Re: Bug with assignments in some commands
  2021-01-18 15:32 Bug with assignments in some commands Patrick Reader
@ 2021-01-18 16:34 ` Peter Stephenson
  2021-01-18 17:40   ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 2021-01-18 16:34 UTC (permalink / raw)
  To: Patrick Reader, zsh-workers


> On 18 January 2021 at 15:32 Patrick Reader <zsh578@pxeger.com> wrote:
> I believe I have found a bug: in arithmetic $(( )) or $[ ] and variable 
> expansions ${ } in some forms of command (pipelines, command 
> substitutions, and inside here-documents and here-strings are the cases 
> I know of so far), assignments to variables do not persist outside the 
> command, almost as if it were in a subshell.

They *are* in a subshell.  That's just how the shell works.

The only difference between zsh and other shells is that some other shells
run the left hand of a pipeline rather than the right hand of a pipeline
in the current shell (if it's shell code, of course), but that's not
something you can rely on.  There is a patch floating around for
a compatibility mode, but in native zsh mode running the right hand
of a pipeline in the current shell, and hence the other parts in
subshells, is a feature.

pws


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

* Re: Bug with assignments in some commands
  2021-01-18 16:34 ` Peter Stephenson
@ 2021-01-18 17:40   ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2021-01-18 17:40 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Patrick Reader, zsh-workers

To expand on what PWS wrote:

echo "$((x++)), x is $x" | cat
echo "${x::=2}, x is $x" | cat

Those are both obvious subshells, forked to the left.  POSIX actually
says that ALL commands in a pipeline are to be subshells, but allows
exceptions.

cat <<<"$((x++))"
cat <<END
$((x++)), x is $x
END

Those should also be obvious, "cat" is an external command so the
entire thing (including the here-document input) is forked off.

<<<"$((x++)), x is $x"
<<END
$((x++)), x is $x
END

Those are less obvious, but they are equivalent to

$NULLCMD <<<"$((x++)), x is $x"
$NULLCMD <<END
$((x++)), x is $x
END

which are again forked as separate processes.


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

end of thread, other threads:[~2021-01-18 17:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-18 15:32 Bug with assignments in some commands Patrick Reader
2021-01-18 16:34 ` Peter Stephenson
2021-01-18 17:40   ` Bart Schaefer

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).