User Tools

Site Tools


informatique:linux:programmation_shell

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
informatique:linux:programmation_shell [2019/04/24 07:16] – [read] pteuinformatique:linux:programmation_shell [2019/04/24 09:36] – [Descripteurs de fichier] pteu
Line 123: Line 123:
   * ''${TAB[0]}'' : contenu du premier enregistrement du tableau TAB   * ''${TAB[0]}'' : contenu du premier enregistrement du tableau TAB
   * ''$TAB'' : équivalent de ''${TAB[0]}''   * ''$TAB'' : équivalent de ''${TAB[0]}''
-  * ''${TAB[*]}'' : désigne l'ensemble des enregistrements du tableau TAB+  * ''${TAB[*]}'' ou ''${TAB[@]}'' : désigne l'ensemble des enregistrements du tableau TAB
  
 Comme pour les variables classiques, on peut récupérer la longueur en le précèdent de ''#'' : Comme pour les variables classiques, on peut récupérer la longueur en le précèdent de ''#'' :
Line 240: Line 240:
 </code> </code>
  
 +
 +======Descripteurs de fichier======
 +
 +Il existe 3 descripteurs de fichier standards, utilisés par toutes les commandes : 0, 1 et 2 correspondants à STDIN, STDOUT et STDERR (input, output et erreur). 0 pointe par défaut sur le clavier, 1 et 2 sont affichés par défaut à l'écran.
 +
 +Pour lire depuis un fichier plutôt que depuis le clavier :
 +<code bash>
 +echo toto > /tmp/fichier.txt
 +read VAR < /tmp/fichier.txt
 +echo $VAR
 + toto
 +</code>
 +
 +====Les redirecteurs====
 +
 +  * ''>'' redirige la sortie vers un fichier ; ''> fichier'' a pour effet de créer un fichier vide ou de supprimer le contenu du fichier s'il existe déjà (équivaut à ''touch fichier''). Pour des raisons de portabilité il vaut mieux utiliser '': > fichier'' qui a le même effet.
 +  * ''<nowiki>>></nowiki>'' possède le même comportement mais écrit à la fin du fichier existant, sans écraser son contenu
 +  * ''&>fichier'' a pour effet de rediriger les flux STDOUT et STDERR dans le fichier.
 +  * ''<'' permet de rediriger un fichier dans l'entrée standard d'une commande, par ex : ''read TOTO < fichier.txt'' (équivaut à ''read TOTO 0< fichier.txt'')
 +
 +Ces redirecteurs sont restaurés à leur valeur par défaut à chaque nouvelle ligne ; en revanche tous les processus fils héritent des descripteurs de leur processus père, à moins que celui-ci ne les ferme (voir plus bas).
 +
 +''|'' est aux flux ce que ''>'' est aux fichiers : il permet de rediriger le flux de sortie d'une commande vers l'entrée d'une autre commande.
 +
 +Pour rediriger le flux d'erreur dans un fichier plutôt que l'afficher à l'écran, on réassigne 2 :
 +<code bash>
 +./prog 2>/tmp/prog_erreur.log
 +</code>
 +
 +Pour rediriger le flux d'erreur sur STDOUT et donc l'envoyer dans le pipe :
 +<code bash>
 +./prog 2>&1 | ./prog2  # prog2 va recevoir en entrée les flux STDOUT et STDERR de prog1
 +# équivaut à
 +./prog |& ./prog2
 +# (depuis bash4, "|&" est reconnue comme abréviation de "2>&1 |")
 +</code>
 +
 +
 +Par défaut ''>'' écrase le fichier existant ; pour ajouter les erreurs à la fin du fichier, on utilise ''>>'' :
 +<code bash>
 +./prog 2>>/tmp/prog_erreur.log
 +</code>
 +Ainsi on conserve les erreurs de chaque exécution du programme.
 +
 +On peut utiliser les descripteurs 3 et plus également, en les initialisant pour ne pas générer d'erreur (ils ne le sont pas par défaut) :
 +<code bash>
 +echo "toto" >&      # erreur "Bad file descriptor"
 +echo "toto" 3>&1 >& # OK, va afficher le résultat sur 3 qui pointe sur 1 qui est la STDOUT
 + toto
 +</code>
 +
 +Pour fermer un descripteur de fichier (le 3 par ex) : ''3>&-''
 +
 +On peut faire pointer un descripteur vers un fichier du système :
 +<code bash>
 +exec 3<> /tmp/foo   # ouverture du fd 3
 +echo toto >&3
 +exec 3>&          # fermeture du fd
 +</code>
 +
 +Exemple d'utilisation d'un descripteur de fichier sur un fichier : écrire un caractère au milieu de ce dernier (src : [[http://tldp.org/LDP/abs/html/io-redirection.html|tldp.org]]).
 +<code bash>
 +#  An application of this is writing at a specified place in a file. 
 +echo 1234567890 > File    # Write string to "File".
 +exec 3<> File             # Open "File" and assign fd 3 to it.
 +read -n 4 <&            # Read only 4 characters.
 +echo -n . >&            # Write a decimal point there.
 +exec 3>&                # Close fd 3.
 +cat File                  # ==> 1234.67890
 +</code>      
  
 ======Les fonctions====== ======Les fonctions======
  
 +=====pipe ("|")=====
 +
 +Le pipe (tube) est une fonction qui permet de chainer la sortie d'une première commande sur l'entrée de la seconde (c'est un tube/canal inter-processus).
 +<code bash>
 +echo "toto et tata" | awk '{$3}'
 + tata
 +</code>
 +
 +Le soucis c'est qu'on ne récupère que le code de retour de la dernière commande du pipe ; et dans l'exemple précédent, awk renvoie toujours 0. Pour résoudre ce soucis, on peut :
 +  * récupérer les codes de retour de chaque commande dans le tableau ''$PIPESTATUS'' (spécifique à bash) :
 +<code bash>
 +false | true
 +echo "${PIPESTATUS[@]}"
 + 1 0
 +</code>
 +  * utiliser la variable ''$pipefail'' (ksh, zsh ou bash) qui va enregistrer le code de retour de la dernière commande qui se terminera en erreur (retour != 0) ; ou à défaut, vaudra 0 si toutes se terminent correctement :
 +<code bash>
 +$ false | true; echo $?
 +0
 +$ set -o pipefail
 +$ false | true; echo $?
 +1
 +</code>
 ===== read ===== ===== read =====
  
Line 251: Line 344:
 Pour afficher un texte avant la saisie on utilise ''-p'' ; on peut récupérer plusieurs saisie d'un seul coup : Pour afficher un texte avant la saisie on utilise ''-p'' ; on peut récupérer plusieurs saisie d'un seul coup :
 <code bash> <code bash>
-read -p "Quel est le nombre indique sur votre CB ? Et le cryptogramme visuel de derrière ?" CARD_NUMBER CRYPTO+read -p "Quel est le numéro de ta CB ? Et le cryptogramme visuel de derrière ?" CARD_NUMBER CRYPTO
 </code> </code>
  
Line 258: Line 351:
 read < fichier.txt read < fichier.txt
  
-souvent utilisé dans une boucle while pour le lire ligne par ligne :+c'est plutôt utilisé dans une boucle whilepour le lire ligne par ligne :
 while read line; do while read line; do
   echo $line   echo $line
Line 275: Line 368:
 done done
 </code> </code>
-Le premier exemple utilise une [[https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html#Process-Substitution|process substitution]], qui permet de référencer l'entrée (''>(list)'') ou la sortie (''<(list)'') d'une commande comme un fichier et non plux un flux ; le second un pipe, mais les 2 se valent.+Le premier exemple utilise une [[https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html#Process-Substitution|process substitution]], qui permet de référencer l'entrée (''>(list)'') ou la sortie (''<(list)'') d'une commande comme un fichier et non plus un flux ; le second un pipe, mais les 2 se valent.
  
 Pour lire depuis une variable : Pour lire depuis une variable :
informatique/linux/programmation_shell.txt · Last modified: 2023/10/02 13:35 by pteu