Quando usar () vs. {} no bash?

58

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

    
por Fat Mind 07.04.2015 / 16:22

4 respostas

77

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

Por exemplo, eu posso usar um subshell se eu:

  • deseja alterar $IFS para alguns comandos, mas não quero alterar $IFS globalmente para o shell atual
  • cd em algum lugar, mas não quero alterar o $PWD do shell atual

Vale a pena observar 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 conclusão da função

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

    
por glenn jackman 07.04.2015 / 16:40
21

Da documentação oficial do bash :

  

()

     
( list )
         

Colocar uma lista de comandos entre parênteses faz com que um ambiente subshell seja criado e cada um dos comandos na lista seja executado nessa sub-camada. Como a lista é executada em um subshell, as atribuições de variáveis não permanecem em vigor depois que a subshell é concluída.

  
     

{}

     
{ list; }
         

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

  
    
por Digital Trauma 07.04.2015 / 21:45
9

O código em '{}' é executado no atual thread / processo / ambiente 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 infantil é geralmente chamado de sub-shell e pode ser pensado como um novo, escopo child-like.

Como exemplo, considere o seguinte ...

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

 ~ # 

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

    
por smokes2345 07.04.2015 / 18:53
4

(...) são usados para executar código em um sub-shell. Código usado entre {...} não será usado em uma sub-casca.

    
por Antoine Orsoni 07.04.2015 / 16:27

Tags