Не может понять замену команды в оболочке Рыбы

В 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)

Кажется, что замена команды только работает параметрами команды, не самой командой? Почему?

Ну, действительно говорится в документе справки

Если параметр будет содержать ряд круглой скобки, то текст, включенный круглой скобкой, будет интерпретироваться как список команд.

Но тем не менее, почему?

6
задан Barett 14 July 2015 в 05:52
поделиться

2 ответа

Как

Это потому, что подстановки команд относятся к расширениям параметров и не допускаются как команды.

Похожий пример:

В 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' - это не простые команды, а зарезервированные слова. См. комментарии ниже.)

.
5
ответ дан 17 December 2019 в 04:41
поделиться

Это связано с порядком расширений.

Из help expand-command-substitution в fish:

При объединении нескольких расширений параметров, расширения выполняются в следующем порядке:

 * Command substitutions
 * Variable expansions
 * Bracket expansion
 * Pid expansion
 * Wildcard expansion

Расширения выполняются справа налево, расширения вложенных скобок выполняются изнутри и снаружи.

Из man bash:

Порядок расширений следующий: расширение скобок, расширение тильды, расширение параметров, переменных и арифметических операций и подстановка команд (выполняется слева направо), разделение слов и расширение имени пути.

0
ответ дан 17 December 2019 в 04:41
поделиться