It seems that bash and zsh will perform the variable and arithmetic expansions in a child process when
a) they're following a redirection operator like <, >, >> or <<<.
b) the command they're part of is not a built-in or function.
bash -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
0
zsh -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
0
ksh -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
7
ksh above is like any other shell except bash or zsh.
This has nothing to do with those being arithmetic expansions: analogously, the same thing happens with
unset i; /bin/echo >${i:=7}.txt; echo $i
will only print 7 in shells other than bash or zsh.
However, as if this weren't bad enough, the behavior is not consistent in any fathomable way between bash and zsh:
bash -c 'i=0; command echo > $((i++)).txt; echo $i'
1
zsh -c 'i=0; command echo > $((i++)).txt; echo $i'
0
bash -c 'i=0; i=$i /usr/bin/printenv i > $((++i)).bash; echo $i; cat *.bash'
0
0
zsh -c 'i=0; i=$i /usr/bin/printenv i > $((++i)).zsh; echo $i; cat *.zsh'
0
1
So, my question is: What does the standard say? Is this acceptable?
I was able to find a lot about variable assignments as in KEY=val cmd and when they may or may not "affect the current execution environment", but nothing about the interaction between redirections, $-expansions and external commands.
And it could NOT be that it also applies to the variable assignments done as part of $-expansions, because ls $((i=2+3)) results in i being set to 5 in all the shells no matter if ls is an external command or a built-in.