3

The example below illustrates the sort of "Daily WTF" that I take zsh scripting to be. I've pretty much given up hope of ever understanding zsh's voluminous rules well enough to be able to figure out such bewildering cases on my own, but I still hope to find some setting, or technique, or tool, or trick, that will at least help me dissect what's going on. Something analogous in spirit to stepping through some code with a debugger, or seeing a trace of its execution.


I thought that ${(%):-%x} was just a sort of cute shorthand for ${(%)NONEXISTENT:-%x}, where NONEXISTENT stands for any identifier that is not defined in the current environment. And indeed, it looks like this is true:

# /tmp/test
echo "${(%)NONEXISTENT:-%x}"
echo "${(%):-%x}"

Results:

% zsh /tmp/test
/tmp/test
/tmp/test

Therefore, I figured, by the same reasoning, that ${(%)-%x} would be just a cute shorthand for ${(%)NONEXISTENT-%x}.

As you probably expect by now, I was wrong. This is shown by the script below, which just extends the script shown earlier with a couple more lines:

# /tmp/test
echo "${(%)NONEXISTENT:-%x}"
echo "${(%):-%x}"
echo "${(%)NONEXISTENT-%x}"
echo "${(%)-%x}"

Result:

% zsh /tmp/test
/tmp/test
/tmp/test
/tmp/test
569X

To add to the mystery, the details depend on whether the script is run or sourced:

% source /tmp/test
/tmp/test
/tmp/test
/tmp/test
5679BJTVXgim
  • What is the purpose of the (%) prompt expansion on the variable? – thrig Oct 17 '15 at 16:22
  • 1
    @thrig: it expanded all % escape in the result as in prompt. Here %x expanded to the name of the file currently run. – cuonglm Oct 17 '15 at 17:33
  • @thrig: also, for some context, see this stackoverflow.com/a/28336473/559827. – kjo Oct 17 '15 at 21:30
3

zsh documentation have a Rules section describing how parameter expansion was applied. You can stick with it to know what the shell will do (AFAIK, there's no debugger for this).


What you thought was quite right, but not in ${(%)-%x} form, because $- is one of the shell special variables, it expanded to the shell options.

So in ${(%)-%x}, the shell was applied flag % to the result of $- with the literal character x at the end removed.

  • Thanks. Those 24 rules you linked to is what I was referring to by "zsh's voluminous rules", and they are one of the reasons I've given up on trying to understand how zsh interprets user input. Besides, even if I had learned those 24 rules by heart, I may not have figured this one out, because for that I would have had to, in addition, have memorized all the special zsh variables, including ones that I never need to use, such as $-. No way. – kjo Oct 17 '15 at 21:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.