Не могу понять подстановку команд в Fish shell - PullRequest
6 голосов
/ 19 июля 2010

В ш:

~$ `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)

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

Ну, справочный документ говорит

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

Но все же, почему?

Ответы [ 2 ]

4 голосов
/ 19 июля 2010

Как

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

Аналогичный пример:

в ш .:

tmpls=ls
$tmpls

Но в рыбе:

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

0 голосов
/ 19 июля 2010

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

С help expand-command-substitution в fish:

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

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

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

С man bash:

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

...