В sh:
~$ `echo ls`
bin/ Desktop/
Но у рыбы:
fish: Illegal command name “(echo ls)”
~% (echo ls)
(Обратите внимание, что сообщение об ошибке появляется выше командной строки.)
~% echo (echo ls)
ls
~% eval (echo ls)
bin/ Desktop/
fish: Illegal command name “(echo ls)”
exec (echo ls)
^
~% exec (echo ls)
Кажется, что замена команды только работает параметрами команды, не самой командой? Почему?
Ну, действительно говорится в документе справки
Если параметр будет содержать ряд круглой скобки, то текст, включенный круглой скобкой, будет интерпретироваться как список команд.
Но тем не менее, почему?
Это потому, что подстановки команд относятся к расширениям параметров и не допускаются как команды.
Похожий пример:
В sh:
tmpls=ls
$tmpls
Но в fish:
% set cmd ls; $cmd
fish: Variables may not be used as commands.
...
Короче говоря, это хорошо для проверяемости
Эта статья объясняет детали:
Поскольку в обычных оболочках разрешено использовать переменные как команды, невозможно надежно проверить синтаксис скрипта. Например, этот фрагмент кода bash/zsh может быть законным или нет, в зависимости от вашей удачи. Чувствуете ли вы себя счастливчиком?
if true; then if [ $RANDOM -lt 1024 ]; then END=fi; else END=true; fi; $END
И bash, и zsh пытаются определить, закончена ли команда в текущем буфере, когда пользователь нажимает клавишу возврата, но из-за проблем, подобных этой, они иногда терпят неудачу. Что еще хуже, этот кусок вполне легального кода отвергается bash:
FI=fi; foo() { if true; then true; $FI; }
Fish избегает такого рода проблем, поскольку переменные не допускаются в качестве команд. Все, что вы можете сделать с переменными как с командами, можно сделать гораздо более чистым способом, используя команду eval или функции.
По той же причине подстановки команд не разрешены в качестве команд.
(Примечание: приведенный пример несправедлив, так как 'if' и 'fi' - это не простые команды, а зарезервированные слова. См. комментарии ниже.)
.Это связано с порядком расширений.
Из help expand-command-substitution
в fish
:
При объединении нескольких расширений параметров, расширения выполняются в следующем порядке:
* Command substitutions
* Variable expansions
* Bracket expansion
* Pid expansion
* Wildcard expansion
Расширения выполняются справа налево, расширения вложенных скобок выполняются изнутри и снаружи.
Из man bash
:
Порядок расширений следующий: расширение скобок, расширение тильды, расширение параметров, переменных и арифметических операций и подстановка команд (выполняется слева направо), разделение слов и расширение имени пути.