[LINUX] Exécution par sous-shell (et mise à jour des variables)

Bonjour. Voici un bref résumé de ce qui se passe lorsqu'il est exécuté par un sous-shell:

  1. Lorsque la commande est entre parenthèses "()" [^ 1].
  2. Avant et après le pipeline.
  3. Lorsqu'une chaîne de caractères / texte est passé à une commande shell et exécuté [^ 2].

Groupe de commande

Si vous en faites un groupe de commandes (c'est-à-dire, mettez-le entre accolades "{}"), il sera traité comme une seule unité d'exécution, et il sera exécuté dans le shell d'origine tel qu'il est [^ 3]. Il existe également des fonctions et `` while do ~ done``` [^ 4] pour gérer des morceaux similaires.

Exemple d'exécution par sous-shell

La combinaison du pipeline et du groupe de commande était facile à mal comprendre. Si vous lisez l'exemple ci-dessous,

command1; command2; { command3; command4; } | { commmand5; command6; }; command7; command8
  1. Ce qui est exécuté dans le shell d'origine est:
  1. Ce qui est exécuté dans le sous-shell est:

Mise à jour des variables dans le sous-shell

Ensuite, compte tenu de la mise à jour de la variable dans le sous-shell, cela ne se propage pas au shell d'origine. Dans l'exemple ci-dessous, la sortie de echo $ n à la fin sera vide.

$ unset n; { n=0; printf 'a\nb\n'; } | cat; echo $n
a
b

$ unset n; printf 'a\nb\n' | (n=0; while read -r line; do n=$((n+1)); done; echo $n); echo $n
2

$ unset n; printf 'a\nb\n' | { n=0; while read -r line; do n=$((n+1)); done; echo $n; }; echo $n
2

$ 

Évitez de "mettre à jour les variables dans le sous-shell"

Si vous mettez à jour des variables dans le shell d'origine, vous pouvez éviter de "mettre à jour les variables dans le sous-shell". L'exemple ci-dessous est encombré, mais `n = 0``` est exécuté dans le shell d'origine et la sortie de la fin` `ʻecho $ n``` est` `0```.

$ unset n; { n=0; printf 'a\nb\n' | cat; } ; echo $n
a
b
0
$

Utilisation de "Here Document"

De même, vous pouvez utiliser le "document ici" pour mettre à jour les variables dans le shell d'origine (vous pouvez éviter le pipeline). Dans l'exemple ci-dessous, la sortie de echo $ n à la fin sera 2```.

$ unset n; { n=0; while read -r line; do n=$((n+1)); done << EOT
 $(printf 'a\nb\n')
EOT
 echo $n; }; echo $n
2
2
$

Alternativement, vous pouvez utiliser Process Substitution dans Bash, etc. au lieu du shell POSIX:

$ unset n; { n=0; while read -r line; do n=$((n+1)); done < <(printf 'a\nb\n'); echo $n; }; echo $n
2
2
$

[^ 1]: Le format de `$ (...)` `pour obtenir la sortie standard de l'exécution du sous-shell entre parenthèses" () "est le même. Cependant, la forme de $ ((...)) est exécutée dans le shell d'origine ("Variations in subshell").

[^ 2]: fait référence à un exemple d'exécution tel que l'exécution d'un script shell ou sh -c'n = 0; echo $ n' `. D'autre part, si vous l'exécutez avec la commande `` source '', il sera exécuté dans le shell d'origine.

[^ 3]: Cela revient à le mettre entre parenthèses "()", mais il n'est pas traité comme un sous-shell.

[^ 4]: Par exemple, `` `printf'a \ nb \ n '| while read -r line; do echo $ line; done```.

Recommended Posts

Exécution par sous-shell (et mise à jour des variables)
Compilation et exécution Java comprises par CLI
Notifier l'erreur et la fin de l'exécution par LINE [Python]
Exécution de la commande déclenchée par la mise à jour du fichier (édition python)
exécution et erreur de pytube
Comment visualiser les données par variable explicative et variable objective
[Route vers Python intermédiaire] Spécifiez dynamiquement la méthode d'exécution par nom de variable