A escolha é sua. Se você não citar $@
, qualquer um dos seus valores sofrerá expansão e interpretação adicionais. Se você citar todos os argumentos passados, a função será reproduzida em sua expansão na íntegra. Você nunca será capaz de lidar de forma confiável com tokens de sintaxe shell como &>|
e etc de qualquer maneira sem analisar os argumentos você mesmo - e então você fica com as opções mais razoáveis de entregar sua função:
- Exatamente as palavras usadas na execução de um único comando simples com
"$@"
.
... ou ...
- Uma versão expandida e interpretada dos seus argumentos, que só então são aplicados juntos como um simples comando com
$@
.
Nenhuma maneira está errada se for intencional e se os efeitos do que você escolher forem bem compreendidos. Ambas as maneiras têm vantagens uma sobre a outra, embora as vantagens da segunda raramente sejam particularmente úteis. Ainda assim ...
(run_this(){ $@; }; IFS=@ run_this 'ls@-dl@/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
... não é inútil , raramente é provável que seja de muito uso . E em um bash
shell, porque bash
não por padrão cola uma definição de variável ao seu ambiente mesmo quando a dita definição é anexada à linha de comando de um especial embutido ou a uma função , o valor global para $IFS
não é afetado e sua declaração é local apenas para a chamada run_this()
.
Da mesma forma:
(run_this(){ $@; }; set -f; run_this ls -l \*)
ls: cannot access *: No such file or directory
... o globbing também é configurável. Citações servem a um propósito - elas não são para nada. Sem eles, a expansão de shell passa por uma interpretação extra - interpretação configurável . Costumava ser - com alguns shells muito antigos - que $IFS
era globalmente aplicado a todos entrada, e não apenas expansões. De fato, as referidas shells se comportaram muito como run_this()
em que elas quebraram todas as palavras de entrada no valor de $IFS
. E assim, se o que você está procurando é um comportamento muito antigo do shell, você deve usar run_this()
.
Eu não estou procurando por isso, e estou bastante pressionado no momento para encontrar um exemplo útil para isso. Eu geralmente prefiro os comandos que meu shell executa para serem aqueles que eu digito nele. E assim, dada a escolha, eu quase sempre run_that()
. Exceto que ...
(run_that(){ "$@"; }; IFS=l run_that 'ls' '-ld' '/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
Apenas sobre qualquer coisa pode ser citada. Comandos serão executados entre aspas. Ele funciona porque, quando o comando é executado, todas as palavras de entrada já foram submetidas a quote-removal - que é o último estágio do processo de interpretação de entrada do shell. Portanto, a diferença entre 'ls'
e ls
só pode importar enquanto o shell estiver sendo interpretado - e é por isso que citar ls
garante que qualquer alias chamado ls
não seja substituído por meu citado ls
palavra de comando. Além disso, as únicas coisas que as citações afetam são a delimitação das palavras (que é como e por que a variável / input-espaço em branco) , e a interpretação de metacaracteres e palavras reservadas.
Então:
'for' f in ...
do :
done
bash: for: command not found
bash: do: unexpected token 'do'
bash: do: unexpected token 'done'
Você nunca poderá fazer isso com run_this()
ou run_that()
.
Mas os nomes das funções, ou $PATH
'd comandos, ou built-in serão executados com a melhor cotação ou sem aspas, e é exatamente assim que run_this()
e run_that()
funcionam. Você não poderá fazer nada útil com $<>|&(){}
desses. Curto de eval
, é.
(run_that(){ "$@"; }; run_that eval printf '"%s\n"' '"$@"')
eval
printf
"%s\n"
"$@"
Mas sem isso, você está limitado aos limites de um comando simples em virtude das aspas que usa (mesmo quando não o faz porque o $@
age como uma citação no início do processo quando o comando é analisado por metacaracteres) . A mesma restrição é válida para as atribuições e redirecionamentos da linha de comando, que são limitados à linha de comando da função. Mas isso não é grande coisa:
(run_that(){ "$@";}; echo hey | run_that cat)
hey
Eu poderia ter tão facilmente <
entrada redirecionada ou >
saída como abri o pipe.
De qualquer forma, de uma maneira circular, não há maneira certa ou errada aqui - cada maneira tem seus usos. É só que você deve escrever como você pretende usá-lo, e você deve saber o que você pretende fazer. Omitir citações pode ter um propósito - caso contrário, não haveria citações
-, mas se você as omitir por razões que não são relevantes para o seu propósito, você está apenas escrevendo um código incorreto. Faça o que você quer dizer; Eu tento de qualquer maneira.