[-- Attachment #1: Type: text/plain, Size: 778 bytes --] Hi, I just spot a following bug on Big Sur zsh 5.8 (x86_64-apple-darwin20.0) $ K="1 2 3" > $ for i in $(for j in $K; do echo "ddd/$j" ; done) ; do echo "$i" ; done > ddd/1 > 2 > 3 > I would expect following output > ddd/1 > ddd/2 > ddd/3 > this breaks referential transparency - sorry for FP buzzwords ;) because $ for i in $(for j in $(echo 1 2 3); do echo "ddd/$j" ; done) ; do echo > "$i" ; done > produce expected output: > ddd/1 > ddd/2 > ddd/3 > I don't know if this is a feature due to some legacy optimizations. I mostly use BASH and this behavior differs from BASH. BASH behaves exactly as I expect. P.S. Wow! Are you still using just a mailing list for bug tracking?! I hope my HTML email will be rendered correctly ;) -- Best regards, Daniil Iaitskov [-- Attachment #2: Type: text/html, Size: 1867 bytes --]
On Thu, Aug 12, 2021 at 11:13:09PM -0400, Daniil Iaitskov wrote: > Hi, > > I just spot a following bug on Big Sur zsh 5.8 (x86_64-apple-darwin20.0) > > $ K="1 2 3" > > $ for i in $(for j in $K; do echo "ddd/$j" ; done) ; do echo "$i" ; done > > ddd/1 > > 2 > > 3 That's because zsh doesn't do word splitting on parameter expansions by default. Running under set -x is illuminating. +zsh:3> j=1 2 3 +zsh:3> echo 'ddd/1 2 3' +zsh:3> i=ddd/1 +zsh:3> echo ddd/1 ddd/1 +zsh:3> i=2 +zsh:3> echo 2 2 +zsh:3> i=3 +zsh:3> echo 3 3 j is assigned '1 2 3' and the result of the command substitution is 'ddd/1 2 3'. However word splitting does happen on unquoted command substitutions, so i is assigned to thrice. > I would expect following output > > > ddd/1 > > ddd/2 > > ddd/3 You want an array: K=(1 2 3) At which point you could skip the command substitution and instead for i in ddd/$^K; do ...
On Thu, Aug 12, 2021, at 11:13 PM, Daniil Iaitskov wrote: > I just spot a following bug on Big Sur zsh 5.8 (x86_64-apple-darwin20.0) It's not a bug. > > $ K="1 2 3" > > $ for i in $(for j in $K; do echo "ddd/$j" ; done) ; do echo "$i" ; done > > ddd/1 > > 2 > > 3 > > I would expect following output > > ddd/1 > > ddd/2 > > ddd/3 By default, zsh does not word-split unquoted parameter expansions; this behavior differs from most Bourne-adjacent shells. Observe that your "inner" loop actually only loops once, with $j taking on the entire value of $K: % K="1 2 3" % for j in $K; do echo "<ddd/$j>"; done <ddd/1 2 3> However, zsh *does* word-split unquoted command substitutions, so the output of $(for j in $K; do echo "ddd/$j" ; done) is split into 'ddd/1', '2', and '3', and $i takes on each value in turn. > > $ for i in $(for j in $(echo 1 2 3); do echo "ddd/$j" ; done) ; do echo "$i" ; done > > produce expected output: > > ddd/1 > > ddd/2 > > ddd/3 In this example, $(echo 1 2 3) is word-split because it is a command substitution. Thus, $j takes on the values '1', '2', and '3', as you expected. > I don't know if this is a feature due to some legacy optimizations. > I mostly use BASH and this behavior differs from BASH. > BASH behaves exactly as I expect. Actually, many zsh users consider the word-splitting of unquoted parameter expansions to be a misfeature, which zsh's default behavior remedies. In any case, it's very much intentional. You can obtain word-splitting behavior with the ${=foo} form: % K="1 2 3" % for j in ${=K}; do echo "<ddd/$j>"; done <ddd/1> <ddd/2> <ddd/3> You can also set SH_WORD_SPLIT, or rewrite the code to use an array. If you're running code that relies on word-splitting (a POSIX script, perhaps), you can run it under sh emulation. > Wow! Are you still using just a mailing list for bug tracking?! Yes. -- vq
Lawrence Velázquez wrote on Fri, 13 Aug 2021 03:50 +00:00:
> On Thu, Aug 12, 2021, at 11:13 PM, Daniil Iaitskov wrote:
> > Wow! Are you still using just a mailing list for bug tracking?!
>
> Yes.
We do have various ways to track bugs, such as Etc/BUGS, but bug
_reports_ should go to the mailing list, yes.