Não é possível entender a substituição de comando no Fish Shell
-
17-09-2020 - |
Pergunta
Em sh:
~$ `echo ls`
bin/ Desktop/
Mas em peixes:
fish: Illegal command name “(echo ls)”
~% (echo ls)
(Observe que a mensagem de erro aparece acima da linha de comando.)
~% echo (echo ls)
ls
~% eval (echo ls)
bin/ Desktop/
fish: Illegal command name “(echo ls)”
exec (echo ls)
^
~% exec (echo ls)
Parece que a substituição de comandos funciona apenas como parâmetros de um comando, não como um comando em si?Por que?
Bem, o médico de ajuda diz
Se um parâmetro contiver um conjunto de parênteses, o texto entre parênteses será interpretado como uma lista de comandos.
Mas ainda assim, por quê?
Solução
Como
Isso porque as substituições de comandos pertencem a expansões de parâmetros e não são permitidas como comandos.
Um exemplo semelhante:
em sh:
tmpls=ls
$tmpls
Mas em peixes:
% set cmd ls; $cmd
fish: Variables may not be used as commands.
...
Por que
Resumindo, é bom para verificabilidade
Esse artigo explica detalhes:
Como é permitido usar variáveis como comandos em shells regulares, é impossível verificar com segurança a sintaxe de um script.Por exemplo, este trecho de código bash/zsh pode ou não ser legal, dependendo da sua sorte.Você se sente com sorte?
if true; then if [ $RANDOM -lt 1024 ]; then END=fi; else END=true; fi; $END
Tanto o bash quanto o zsh tentam determinar se o comando no buffer atual é concluído quando o usuário pressiona a tecla Enter, mas devido a problemas como esse, às vezes eles falham.Pior ainda, este código perfeitamente legal é rejeitado pelo bash:
FI=fi; foo() { if true; then true; $FI; }
Fish evita esse tipo de problema, já que variáveis não são permitidas como comandos.Qualquer coisa que você possa fazer com variáveis como comandos pode ser feito de uma maneira muito mais limpa usando o comando eval ou usando funções.
Pela mesma razão, substituições de comandos não são permitidas como comandos.
(Observação:O exemplo citado não é justo, pois 'if' e 'fi' não são comandos simples, mas palavras reservadas.Veja os comentários abaixo.)
Outras dicas
Tem a ver com a ordem das expansões.
De help expand-command-substitution
em fish
:
Ao combinar várias expansões de parâmetros, as expansões são realizadas na seguinte ordem:
* Command substitutions
* Variable expansions
* Bracket expansion
* Pid expansion
* Wildcard expansion
As expansões são realizadas da direita para a esquerda, as expansões do suporte aninhado são realizadas de dentro e por fora.
De man bash
:
A ordem das expansões é:Expansão de cinta, expansão, parâmetro, expansão variável e aritmética e substituição de comando (feita de maneira esquerda para a direita), divisão de palavras e expansão do nome do caminho.