为什么 zsh 允许 ${name:-word} 中的 name 为空?

为什么 zsh 允许 ${name:-word} 中的 name 为空?

zsh 文档:

${名称-单词}

${名称:-单词}

如果名称已设置,或者在第二种形式中为非空,则替换其值;否则替换单词。在第二种形式中,名称可以省略,在这种情况下,总是用单词代替。

所以我可以使用类似的东西:

$ printf '%s\n' ${:-123}
123

我想知道为什么zsh允许这样做以及在什么情况下它有用?

答案1

我没有解释为什么他们是这样做的,但${:-foo...}确实有一个应用程序:它在语法上需要参数替换的地方算作参数替换,但总是只是扩展到您给出的文字。你可以写这样的东西来使用扩展标志或者其他扩展说明符在原地文字字符串上:

$ echo ${(#)${=${:-65 66 67}}}
A B C
$ echo ${(q)${:-hello world!}}
hello\ world\!

你也可以word在字符串中使用其他扩展:

$ restofarglist=arg3,arg4
$ echo ${${:-arg1,arg2,$restofarglist}//,/ }

所有这些行为都被正确记录在参数扩展部分的末尾:

如果使用${...}类型参数表达式或$(...)类型命令替换来代替姓名上面,它首先被扩展,并且结果被使用,就好像它是姓名

您可以任意深度地嵌套这些扩展,尽管它们很快就会变得难以理解。${name=word}在两侧使用扩展族都会出现奇怪的极端情况。

一般来说,这是一种相当迟钝的做事方式,但它既是我所知道的唯一应用程序,${:-}也是在不创建另一个变量的情况下实现这些事情的唯一方法。尽管所有的内容在技术上都已经存在,但文档肯定会更清晰。

答案2

当与参数扩展的其他功能结合使用时,它允许您执行一些巧妙的技巧。

几个例子:

# strftime date via prompt sequences
tar -cpf ${(%):-%D{%Y%m%d}}-/etc.tar /etc
# brace expansion, but separated by commas via PE flags and nesting PEs.
print ${(j:,:)${:-{1..10}}}

相关内容