<Précédent | Table des matières | Suivant>
Substitution de processus
Bien qu'elles se ressemblent et puissent toutes les deux être utilisées pour combiner des flux pour la redirection, il existe une différence importante entre les commandes de groupe et les sous-shells. Alors qu'une commande de groupe exécute toutes ses commandes dans le shell actuel, un sous-shell (comme son nom l'indique) exécute ses commandes dans une copie enfant du shell actuel. Cela signifie que l'environnement est copié et donné à une nouvelle instance du shell. Lorsque le sous-shell se ferme, la copie de l'environnement est perdue, de sorte que toutes les modifications apportées à l'environnement du sous-shell (y compris l'affectation de variables) sont également perdues. Par conséquent, dans la plupart des cas, à moins qu'un script ne nécessite un sous-shell, les commandes de groupe sont préférables aux sous-shells. Les commandes de groupe sont à la fois plus rapides et nécessitent moins de mémoire.
Nous avons vu un exemple de problème d'environnement de sous-shell au chapitre 28, lorsque nous avons découvert qu'un lire commande dans un pipeline ne fonctionne pas comme on pourrait s'y attendre intuitivement. Pour récapituler, si nous construisons un pipeline comme celui-ci :
echo "toto" | read echo $REPLY
echo "toto" | read echo $REPLY
Le contenu de la RÉPONDRE variable est toujours vide car le lire La commande est exécutée dans un sous-shell, et sa copie de RÉPONDRE est détruit lorsque le sous-shell se termine.
Étant donné que les commandes dans les pipelines sont toujours exécutées dans des sous-shells, toute commande qui attribue des variables rencontrera ce problème. Heureusement, le shell fournit une forme exotique d'expansion appelée substitution de processus qui peut être utilisé pour contourner ce problème.
La substitution de processus s'exprime de deux manières : Pour les processus qui produisent une sortie standard :
<(liste)
ou, pour les processus qui acceptent l'entrée standard :
>(liste)
De liste est une liste de commandes.
Pour résoudre notre problème avec lire, nous pouvons utiliser la substitution de processus comme ceci :
lire < <(echo "foo") echo $REPLY
lire < <(echo "foo") echo $REPLY
La substitution de processus nous permet de traiter la sortie d'un sous-shell comme un fichier ordinaire à des fins de redirection. En fait, puisqu'il s'agit d'une forme d'expansion, on peut examiner sa valeur réelle :
[moi@linuxbox ~]$ echo <(echo "foo")
/dev/fd/63
[moi@linuxbox ~]$ echo <(echo "foo")
/dev/fd/63
En utilisant echo pour voir le résultat de l'expansion, nous voyons que la sortie du sous-shell est fournie par un fichier nommé /dev/fd/63.
La substitution de processus est souvent utilisée avec des boucles contenant lire. Voici un exemple de
boucle de lecture qui traite le contenu d'une liste de répertoires créée par un sous-shell :
#! / Bin / bash
# pro-sub : démo de substitution de processus
lors de la lecture attr liens propriétaire groupe taille date heure nom de fichier ; faire chat <<- EOF
Nom de fichier : $filename Taille : $size
Propriétaire : $propriétaire
Groupe : $group Modifié : $date $time Liens : $links Attributs : $attr
EOF
fait < <(ls -l | tail -n +2)
#! / Bin / bash
# pro-sub : démo de substitution de processus
lors de la lecture attr liens propriétaire groupe taille date heure nom de fichier ; faire chat <<- EOF
Nom de fichier : $filename Taille : $size
Propriétaire : $propriétaire
Groupe : $group Modifié : $date $time Liens : $links Attributs : $attr
EOF
fait < <(ls -l | tail -n +2)
La boucle s'exécute lire pour chaque ligne d'une liste d'annuaire. La liste elle-même est produite sur la dernière ligne du script. Cette ligne redirige la sortie de la substitution de processus vers l'entrée standard de la boucle. Les queue La commande est incluse dans le pipeline de substitution de processus pour éliminer la première ligne de la liste, ce qui n'est pas nécessaire.
Lorsqu'il est exécuté, le script produit une sortie comme celle-ci :
[moi@linuxbox ~]$ sous-pro | tête -n 20
Nom de fichier : address.ldif Taille : 14540
Propriétaire : moi
Groupe : moi
Modified: 2009-04-02 11:12
[moi@linuxbox ~]$ sous-pro | tête -n 20
Nom de fichier : address.ldif Taille : 14540
Propriétaire : moi
Groupe : moi
Modified: 2009-04-02 11:12
Liens:
1
Liens:
Attributs : -rw-r--r--
Nom de fichier : bin
Taille: 4096
Propriétaire : moi
Groupe : moi
Modified: 2009-07-10 07:31
Liens : 2
Attributs : drwxr-xr-x
Nom du fichier : bookmarks.html Taille : 394213
Propriétaire : moi
Groupe : moi
Attributs : -rw-r--r--
Nom de fichier : bin
Taille: 4096
Propriétaire : moi
Groupe : moi
Modified: 2009-07-10 07:31
Liens : 2
Attributs : drwxr-xr-x
Nom du fichier : bookmarks.html Taille : 394213
Propriétaire : moi
Groupe : moi