Почему zsh разрешает имя null в $ {name: -word}?

Из документации zsh :

$ {Имя-слово}

$ {Имя: -слово}

Если имя задано или во второй форме не равно null, замените его значение; иначе замените слово. Во второй форме имя может быть опущено, и в этом случае слово всегда заменяется.

Поэтому я могу использовать что-то вроде:

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

Интересно, почему zsh позволяет это, и в этом случае это полезно?

У меня нет объяснения, почему они сделали это таким образом, но у ${:-foo...} есть приложение: он считается заменой параметра в местах, которые синтаксически требуют одного, но всегда просто расширяются до литерала вы даете. Вы можете написать такие вещи, как использование флажков расширения или других спецификаторов расширения в литеральной строке на месте:

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

Вы также можете использовать другие расширения внутри своей word строки :

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

Все это поведение задокументировано в конце раздела по расширению параметра :

Если вместо имени выше используется выражение параметра типа ${...} или подстановка команды типа $(...) , то оно сначала разворачивается, а результат используется так, как если бы оно было значением имени .

Вы можете вложить эти расширения произвольно глубоко, хотя они становятся непостижимыми довольно быстро. Существуют странные угловые случаи вокруг использования семейства расширений ${name=word} внутри каждой стороны.

Это довольно тупой способ делать вещи в целом, но это единственное приложение, которое я знаю для ${:-} и единственный способ сделать эти вещи без создания другой переменной. Документация может быть четче, хотя все биты там технически существуют.

В сочетании с другими функциями разложения параметров он позволяет вам сделать несколько умных трюков.

Несколько примеров:

 # 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}}}