zsh: zparseopts not behaving as expected

Viewed 258

It seems that I must be using zparseopts incorrectly, because I'm not getting what the expected output is for this simple example scripts.

zparseopts seems to erroneously assume that -h and --help take an argument, even though they are declared without the :.

set -- --help --checkout foo 1 2 3 4

declare -A misc

zparseopts -E -D -K \
        -A misc \
        '-checkout:' \
        h \
        -help

for k v in ${(@kv)misc}; do
    echo flag $k: $v
done

echo "argv $@"

This should print out

flag --help:
flag --checkout: foo
argv 1 2 3 4

But instead prints as if --help took an argument. Am I using the -A and associative array incorrectly?

flag --help: --checkout
flag foo:
argv: 1 2 3 4
1 Answers

Turns out that zparseopts is doing exactly what you want. The issue is that the later echo statements are not displaying the keys and values in the associative array correctly.

Unusually for zsh, you need more quotes. Try replacing the for loop with this:

printf 'flag %s: %s\n' "${(kv@)misc}"

The real fix is the double quotes paired with the @ parameter expansion flag; this ensures that empty values will be treated as separate words in the result. The printf is just a shorter way to loop through the key-value pairs.

You can also display the value of an associative array (or almost any variable) with typeset:

typeset '@' 'misc'
Related