web-dev-qa-db-fra.com

Quand utiliser () contre {} dans bash?

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?

71
Fat Mind

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

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

  • veux 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 persistent une fois la fonction terminée

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

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

Documentation

85
glenn jackman

De l’officiel documentation bash :

()

( list )

Le fait de placer une liste de commandes entre parenthèses entraîne la création d’un environnement de sous-shell et l’exécution de chacune des commandes de la liste dans ce sous-shell. Comme la liste est exécutée dans un sous-shell, les affectations de variables ne restent pas en vigueur une fois le sous-shell terminé.

{}

{ list; }

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

23
Digital Trauma

Le code dans '{}' est exécuté dans le thread/processus/environnement actuel et les modifications sont conservées. Pour le dire plus succinctement, le code est exécuté dans la portée actuelle.
Le code dans '()' est exécuté dans un processus enfant distinct de bash qui est ignoré après l'exécution. Ce processus enfant est souvent appelé un sous-shell et peut être considéré comme un nouveau domaine d'application semblable à celui d'un enfant.

A titre d'exemple, considérons ce qui suit ...

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

 ~ # 

Notez que dans le premier exemple avec '{}', 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 de la portée de '()'.

9
smokes2345

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

4
Antoine Orsoni