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?
Vous vouliez dire dans le contexte du groupe de commandes seulement?
Heemayl
Réponses:
87
Si vous souhaitez que les effets secondaires de la liste de commandes affectent votre shell actuel , utilisez {...}
Si vous souhaitez supprimer tout effet secondaire, utilisez(...)
Par exemple, je pourrais utiliser un sous-shell si je:
veux modifier $IFSquelques commandes, mais je ne veux pas modifier $IFSglobalement le shell actuel
cdquelque part, mais je ne veux pas changer le $PWDpour 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
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
Après de nombreuses années de développement de shell, je ne savais pas que vous pouviez utiliser des parenthèses pour exécuter des fonctions dans des sous-shell. Quelle bonne idée d'éviter de polluer l'espace de noms mondial!
l0b0
7
L'utilisation du localmot clé contribue largement à réduire cette pollution.
Glenn Jackman
2
Oui, mais vous devez vous rappeler de déclarer chaque variable locale, et cela encombrerait le code.
l0h08 le
4
Astuce: Si vous voulez des fonctions sans effets secondaires tout en évitant la syntaxe inhabituelle de déclaration de fonctions (que les éditeurs de code ne connaissent peut-être pas), utilisez simplement des parenthèses sur l'appel de fonction plutôt que la déclaration:pwd; (count_tmp); pwd;
Juve
2
à la coquille ... foo () (:;) est équivalent à foo () {(:;); } C'est comme ça que ça se passe si vous le demandez!
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 actuel du shell. Aucun sous-shell n'est créé. La liste suivante point-virgule (ou nouvelle ligne) est requise.
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 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.
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 '()'.
Réponses:
Si vous souhaitez que les effets secondaires de la liste de commandes affectent votre shell actuel , utilisez
{...}
Si vous souhaitez supprimer tout effet secondaire, utilisez
(...)
Par exemple, je pourrais utiliser un sous-shell si je:
$IFS
quelques commandes, mais je ne veux pas modifier$IFS
globalement le shell actuelcd
quelque part, mais je ne veux pas changer le$PWD
pour le shell actuelIl 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
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
Documentation
la source
local
mot clé contribue largement à réduire cette pollution.pwd; (count_tmp); pwd;
De la documentation officielle de bash :
la source
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 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 ...
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 '()'.
la source
(...)
sont utilisés pour exécuter du code dans un sous-shell. Le code utilisé{...}
avant ne sera pas utilisé dans un sous-shell.la source