Posso definir bash
funções usando ou omitindo a function
palavra-chave. Existe alguma diferença?
#!/bin/bash
function foo() {
echo "foo"
}
bar() {
echo "bar"
}
foo
bar
Ambas as chamadas para funções foo
são bar
bem-sucedidas e não consigo ver nenhuma diferença. Então, estou me perguntando se é apenas para melhorar a legibilidade ou se há algo que estou faltando ...
BTW em outros shells como dash
( /bin/sh
tem link simbólico dash
no debian/ubuntu) ele falha ao usar a function
palavra-chave.
Responder1
A razão pela qual existem duas sintaxes diferentes é histórica. A function
palavra-chave veio deksh. A sintaxe inspirada em C ()
veio doConcha Bourne.POSIXpadroniza apenas a foo ()
sintaxe Bourne. Bash e zsh suportam ambos, assim como o hybrid function foo () { … }
. Exceto no ATT ksh, a função resultante é exatamente a mesma.
Cuidado com uma pegadinha com a ()
sintaxe: o nome da função está sujeito à expansão do alias.
alias f=g
f () { echo foo; }
type f # f is an alias for g
type g # g is a shell function
f # alias f → function g → print foo
\f # no alias lookup → f: not found
g # function g
No ATT ksh (mas não no pdksh e seus descendentes, como mksh), existem algumas diferenças entre funções definidas por function
e funções definidas com a sintaxe Bourne/POSIX. Nas funções definidas por function
, a typeset
palavra-chave declara uma variável local: assim que a função termina, o valor da variável é redefinido para o que era antes de entrar na função. Com a sintaxe clássica, as variáveis têm um escopo global, quer você use typeset
ou não.
$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global
Outra diferença no ksh é que as funções definidas com a function
palavra-chave possuem seu próprio contexto de trap. As armadilhas definidas fora da função são ignoradas durante a execução da função, e erros fatais dentro da função saem apenas da função e não de todo o script. Além disso, $0
o nome da função em uma função é definido por, function
mas o nome do script em uma função é definido com ()
.
Pdksh não emula ATT ksh. No pdksh, typeset
cria variáveis com escopo local, independentemente da função, e não há armadilhas locais (embora o uso function
faça algumas pequenas diferenças - consulte a página de manual para obter detalhes).
Bash e zsh introduziram a function
palavra-chave para compatibilidade com ksh. No entanto, nesses shells function foo { … }
e foo () { … }
são estritamente idênticos, assim como as extensões bash e zsh function foo () { … }
(exceto para potencial expansão de alias ao analisar a definição, conforme explicado acima). A typeset
palavra-chave sempre declara variáveis locais (exceto com, -g
é claro), e as armadilhas não são locais (você pode obter armadilhas locais no zsh definindo a local_traps
opção).
Responder2
Não há diferença no AFAIK, a não ser o fato da segunda versão ser mais portátil.
Responder3
foo() any-command
é a sintaxe Bourne suportada por qualquer shell do tipo Bourne, mas bash
,yash
e versões recentes de posh
(que suportam apenas comandos compostos). (o Bourne Shell e as implementações da AT&T ksh
não suportam, foo() any-command > redirections
a menos que any-command
seja um comando composto).
foo() any-compound-command
(exemplos de comandos compostos: { cmd; }
, for i do echo "$i"; done
, (cmd)
... sendo o mais comumente usado { ...; }
)
é a sintaxe POSIX suportada por qualquer shell do tipo Bourne e aquela que você geralmente deseja usar.
function foo { ...; }
é a sintaxe do shell Korn, que antecede a sintaxe Bourne. Use este apenas se estiver escrevendo especificamente para a implementação da AT&T do shell Korn e precisar do tratamento específico que recebe lá. Essa sintaxe não é POSIX, mas é suportada por bash
e para compatibilidade com o shell Korn, embora esses shells (e as yash
variantes baseadas em -do shell Korn) não a tratem de maneira diferente da sintaxe padrão.zsh
pdksh
function foo () { ...; }
é a sintaxe denãocasca enão deve ser usado. Acontece que ele só é suportado acidentalmente por bash
, e pelas variantes baseadas no shell Korn. Aliás, é também a sintaxe da função.yash
zsh
pdksh
awk
Se continuarmos descendo na lista esotérica,
function foo() other-compound-command
(como function foo() (subshell)
ou function foo() for i do; ... done
) é ainda pior. É suportado por bash
, yash
e zsh
, mas não por ksh, mesmo pelas pdksh
variantes baseadas em -.
Enquanto:
function foo() simple command
só é suportado por zsh
.
foo bar() any-command
Ou ainda:
$function_list() any-command
Definir várias funções ao mesmo tempo só é suportado porzsh
function { body; } args
() any-compound-command args
Que sãofunção anônimainvocações, são suportadas apenas por zsh
também.
Responder4
Vários outros já responderam corretamente, mas aqui está minha sinopse concisa:
A segunda versão é portátil e provavelmente funcionará com muitos shells padrão (particularmente POSIX).
A primeira versão funcionará apenas com bash, mas você pode omitir os parênteses após o nome da função.
Caso contrário, eles representam entidades idênticas após o bash interpretá-los.