#89 zsh expands command substitutions incorrectly in local statements


See the following script for an example:

local a=$(echo b c=d)
echo -e "local a=\$(echo b c=d)\n  a=[$a]\n  c=[$c]\n"

a=$(echo b c=d)
echo -e "a=\$(echo b c=d)\n  a=[$a]\n  c=[$c]\n"

foo="b c=d"
local a=$foo
echo -e "foo=\"b c=d\"\nlocal a=\$foo\n  a=[$a]\n  c=[$c]\n"

echo -e "a=\$foo\n  a=[$a]\n  c=[$c]\n"

These should all result in the same thing (a=[b c=d] c=[]), and in fact do in POSIX sh (although it needs to be wrapped in a function for local to work). But in zsh, the first version outputs a=[b] c=[d]. But this is not even internally consistent, since the other permutations all expand to a single word.


  • Bart Schaefer

    Bart Schaefer - 2013-02-01

    "local" is not included in the POSIX spec (not that it would matter to native zsh mode whether it was). So whatever you're calling "POSIX shell" isn't strictly one. However:

    Some shells treat "local" [and "typeset"] as a special syntactic element and therefore treat any arguments that follow it as assignment syntax. Zsh is not one of those shells; the arguments to "local" are just normal command-line arguments like those to any other command. This is why, for example, you can't write

    local ary=(array assignment)

    among other things.

    $(...) is always substituted as an array, which is why your first example behaves as it does. In assignment contexts, arrays assigned with scalar syntax are joined, which is why your second example behaves as it does.

    In the third example, $foo is a scalar, and zsh does not split scalar variable references on whitespace when expanding. If you tried instead

    foo=( b c=d )
    local a=$foo

    you would find it behaves like the first example.

    Your fourth example shouldn't need further explanation.

  • Bart Schaefer

    Bart Schaefer - 2013-02-01
    • status: open --> closed-wont-fix
    • milestone: feature_requests --> dead
  • Peter Stephenson

    The one thing Bart didn't point out is that there is an option to get (at least approximately) the behaviour you expect, namely KSH_TYPESET (from the shell and command where this difference was first encountered). Not surprisingly this is set when emulating POSIX-style shells. It doesn't make commands like "local" syntactically special other than for word splitting, however: you still can't assign arrays there, for example.


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.

No, thanks