J'étudie le Shell scripting avec bash et j'ai besoin de connaître la différence entre (...)
y {...}
. Comment choisir entre les deux lorsqu'on écrit un script ?
Réponses
Trop de publicités?Si vous voulez que les effets secondaires de la liste de commande affectent votre actuel Shell, utilisez {...}
Si vous voulez vous débarrasser des effets secondaires, utilisez (...)
Par exemple, je pourrais utiliser un subshell si :
- veulent 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 la$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
-
utilisation inhabituelle : parenthèses : le corps de la fonction s'exécute dans un sous-shell ; les effets secondaires disparaissent lorsque le sous-shell sort.
$ cd ; unset files $ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}") $ pwd; count_tmp; pwd /home/jackman 11 /home/jackman $ echo "${#files[@]}" 0
De l'officiel documentation bash :
()
( list )
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 après la fin du sous-shell.
{}
{ list; }
Placer une liste de commandes entre accolades entraîne l'exécution de la liste dans le contexte actuel de Shell. Aucun sous-shell n'est créé. Le point-virgule (ou la nouvelle ligne) qui suit la liste est obligatoire.
Le code figurant dans "{}" est exécuté dans le fil, le processus ou l'environnement actuel et les modifications sont préservées. En d'autres termes, le code est exécuté dans la portée actuelle.
Le code dans '()' est exécuté à l'intérieur d'un processus enfant séparé de bash qui est abandonné après l'exécution. Ce processus enfant est souvent appelé sub-Shell et peut être considéré comme un nouveau processus enfant.
A titre d'exemple, considérez ce qui suit...
~ # { test_var=test ; }
~ # echo $test_var
test
~ # ( test_var2=test2 )
~ # echo $test_var2
~ #
Remarquez que dans le premier exemple avec " {} ", la variable est toujours définie même après le " } " de fermeture, alors que dans l'exemple avec "() ", la variable n'est pas définie en dehors de la portée du "() ".
Notez également la différence de syntaxe entre "{}" et "()". Le délimiteur " ;" est toujours requis pour le code dans '{}', mais pas pour le code dans '()'.