Quand utiliser () vs. {} dans bash?

59

J'étudie les scripts shell avec bash et j'ai besoin de connaître la différence entre (...) et {...} . Comment peut-on choisir entre les deux lors de l'écriture d'un script?

    
posée Fat Mind 07.04.2015 - 16:22
la source

4 réponses

78

Si vous souhaitez que les effets secondaires de la liste de commandes affectent votre shell actuel , utilisez {...}
Si vous voulez ignorer les effets secondaires, utilisez (...)

Par exemple, je pourrais utiliser un sous-shell si je:

  • souhaitez modifier $IFS pour quelques commandes, mais je ne veux pas modifier $IFS globalement pour le shell actuel
  • cd quelque part, mais je ne veux pas changer le $PWD pour le shell actuel

Il est intéressant de noter que les parenthèses peuvent être utilisées dans une définition de fonction:

  • utilisation normale: accolades: le corps de la fonction s'exécute dans le shell actuel; les effets secondaires restent après la fin de la fonction

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • usage inhabituel: parenthèses: le corps de la fonction s'exécute dans un sous-shell; les effets secondaires disparaissent lorsque la sous-couche se termine

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

Documentation

    
réponse donnée glenn jackman 07.04.2015 - 16:40
la source
21

De la documentation bash officielle :

  

()

     
( list )
         

Si vous placez une liste de commandes entre parenthèses, un environnement de sous-shell sera créé et chacune des commandes de la liste sera exécutée dans ce sous-shell. Comme la liste est exécutée dans un sous-shell, les affectations de variables ne restent pas en vigueur après la fin du sous-shell.

  
     

{}

     
{ list; }
         

Si vous placez une liste de commandes entre accolades, la liste sera exécutée dans le contexte actuel du shell. Aucun sous-shell n'est créé. Le point-virgule (ou nouvelle ligne) la liste suivante est requise.

  
    
réponse donnée Digital Trauma 07.04.2015 - 21:45
la source
9

Le code dans '{}' est exécuté dans le thread / processus / environnement actuel et les modifications sont conservées, pour être plus succinct, le code est exécuté dans la portée actuelle.
Le code dans '()' est exécuté dans un processus enfant séparé de bash qui est supprimé après exécution. Ce processus enfant est souvent appelé sous-shell et peut être considéré comme une nouvelle portée de type enfant.

À titre d’exemple, considérons ce qui suit ...

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

 ~ # 

Remarquez dans le premier exemple avec '{}' que la variable est toujours définie même après la fermeture '}', alors que dans l'exemple avec '()' la variable n'est pas définie en dehors du champ '()'.

    
réponse donnée smokes2345 07.04.2015 - 18:53
la source
4

(...) sont utilisés pour exécuter du code dans un sous-shell. Le code utilisé avant {...} ne sera pas utilisé dans un sous-shell.

    
réponse donnée Antoine Orsoni 07.04.2015 - 16:27
la source

Lire d'autres questions sur les étiquettes