diferença entre “function foo () {}” e “foo () {}”

80

Eu posso definir bash funções usando ou omitindo a palavra-chave function . Existe alguma diferença?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

As chamadas para as funções foo e bar são bem-sucedidas e não vejo nenhuma diferença. Então, eu estou querendo saber se é apenas para melhorar a legibilidade, ou há algo que estou perdendo ...

BTW em outros shells como dash ( /bin/sh é linkado por símile para dash no debian / ubuntu) ele falha ao usar a palavra-chave function .

    
por Carlos Campderrós 26.04.2013 / 13:24

5 respostas

39

Não há diferença AFAIK, além do fato de que a segunda versão é mais portátil.

    
por 26.04.2013 / 13:30
72

A palavra-chave function foi introduzida em ksh . O tradicional shell Bourne só tinha a sintaxe foo () e POSIX padroniza apenas a sintaxe foo () .

No ATT ksh (mas não no pdksh), existem algumas diferenças entre as funções definidas por function e as funções definidas com a sintaxe Bourne / POSIX. Nas funções definidas por function , a palavra-chave typeset declara uma variável local: assim que a função sai, 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, independentemente de você usar 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 palavra-chave function têm seu próprio contexto de trap. Traps definidos fora da função são ignorados durante a execução da função, e os erros fatais dentro da função saem apenas da função e não do script inteiro. Além disso, $0 é o nome da função em uma função definida por function , mas o nome do script em uma função definida com () .

O Pdksh não emula o ATT ksh. Em pdksh, typeset cria variáveis de escopo local independentemente da função e não há traps locais (embora usar function faça algumas pequenas diferenças - consulte a man page para detalhes).

Bash e zsh introduziram a palavra-chave function para compatibilidade com o ksh. No entanto, nesses shells, function foo { … } e foo () { … } são estritamente idênticos, assim como a extensão bash e zsh function foo () { … } . A palavra-chave typeset sempre declara variáveis locais (exceto com -g , é claro) e as traps não são locais (você pode obter traps locais em zsh definindo a opção local_traps ).

    
por 27.04.2013 / 03:35
29
foo() any-command

é a sintaxe Bourne suportada por qualquer shell parecido com o Bourne, mas bash , yash e recente versões de posh (que suportam apenas comandos compostos). (as implementações da shell Bourne e AT & T de 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 parecido com o Bourne e aquele que você geralmente quer usar.

function foo { ...; }

é a sintaxe do shell Korn, que antecede a sintaxe Bourne. Use este somente se escrever especificamente para a implementação do AT & T da shell Korn e precisar do tratamento específico que ele recebe lá. Essa sintaxe não é POSIX, mas é suportada por bash , yash e zsh para compatibilidade com o shell Korn, embora esses shells (e as variantes pdksh -based do shell Korn) não tratem qualquer diferente da sintaxe padrão.

function foo () { ...; }

é a sintaxe do shell no e não deve ser usada . Acontece que ele é suportado acidentalmente por bash , yash , zsh e as variantes baseadas em pdksh do shell Korn. Aliás, é também a sintaxe da função awk .

Se continuarmos a descer a 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 pelo ksh, mesmo as variantes baseadas em pdksh .

Enquanto:

function foo() simple command

é suportado apenas por zsh .

    
por 29.04.2013 / 14:02
22

Semanticamente, essas duas formas são equivalentes no Bash.

Da página do manual:

Shell functions are declared as follows:

name () compound-command [redirection]
function name [()] compound-command [redirection]

This defines a function named name. The reserved word function is optional. If the function reserved word is supplied, the parentheses are optional.

EDIT: Acabei de notar que esta questão está marcada com posix . No POSIX sh , a palavra-chave function não é usada (embora esteja reservada).

    
por 26.04.2013 / 14:33
1

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 o bash, mas você pode omitir os parênteses após o nome da função.

Caso contrário, eles representam entidades idênticas depois que o bash as interpreta.

    
por 01.12.2015 / 09:47