Quando usar () vs. {} no bash?


74

Estou estudando scripts de shell com o bash e preciso saber a diferença entre (...)e {...}. Como alguém seleciona entre os dois ao escrever um script?



3
Você quis dizer apenas no contexto do agrupamento de comandos?
heemayl

Respostas:


87

Se você deseja que os efeitos colaterais da lista de comandos afetem seu shell atual , use {...}
Se você deseja descartar quaisquer efeitos colaterais, use(...)

Por exemplo, eu poderia usar um subshell se eu:

  • quero alterar $IFSpara alguns comandos, mas não quero alterar $IFSglobalmente para o shell atual
  • cdem algum lugar, mas não quero alterar o $PWDshell atual

Vale a pena notar que os parênteses podem ser usados ​​em uma definição de função:

  • uso normal: chaves: corpo da função é executado no shell atual; efeitos colaterais permanecem após a função ser concluída

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • uso incomum: parênteses: o corpo da função é executado em um subshell; efeitos colaterais desaparecem quando o subshell sai

    $ cd ; unset files
    $ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /home/jackman
    $ echo "${#files[@]}"
    0
    

Documentação


11
Após muitos anos de desenvolvimento de shell, eu não sabia que você poderia usar parênteses para executar funções em subshells. Que ótima idéia para evitar poluir o espaço para nome global!
L0b0:

7
O uso da localpalavra - chave ajuda bastante na limpeza dessa poluição.
glenn jackman

2
Sim, mas você deve se lembrar de declarar todas as variáveis ​​locais, e isso atrapalha o código.
L0b0

4
Dica: Se você deseja funções sem efeito colateral, mas evita a sintaxe incomum de declaração de função (da qual os editores de código podem não estar cientes), basta usar parênteses na chamada de função em vez da declaração:pwd; (count_tmp); pwd;
Juve

2
para o shell ... foo () (:;) é equivalente a foo () {(:;); } É assim que ele relata, se você perguntar!
Anthony

23

A partir da documentação oficial do bash :

()

( list )

Colocar uma lista de comandos entre parênteses causa a criação de um ambiente de subshell, e cada um dos comandos na lista é executado nesse subshell. Como a lista é executada em um subshell, as atribuições de variáveis ​​não permanecem em vigor após a conclusão do subshell.

{}

{ list; }

Colocar uma lista de comandos entre chaves faz com que a lista seja executada no contexto atual do shell. Nenhum subshell é criado. É necessário o ponto e vírgula (ou nova linha) a seguir.


9

O código em '{}' é executado no thread / processo / ambiente atual e as alterações são preservadas, para ser mais sucinto, o código é executado no escopo atual.
O código em '()' é executado dentro de um processo filho separado do bash que é descartado após a execução. Esse processo filho geralmente é chamado de subcasca e pode ser considerado como um novo escopo infantil.

Como exemplo, considere o seguinte ...

 ~ # { test_var=test }
 ~ # echo $test_var
 test
 ~ # ( test_var2=test2 )
 ~ # echo $test_var2

 ~ # 

Observe no primeiro exemplo com '{}' a variável ainda está definida mesmo após o fechamento '}', enquanto no exemplo com '()' a variável não está definida fora do escopo de '()'.


4

(...)são usados ​​para executar código em um sub-shell. O código usado bewteen {...}não será usado em um sub-shell.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.