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:53] – [pipe ("|")] pteuinformatique:linux:programmation_shell [2020/01/24 07:50] – [Nombres, comparaison] tester si VAR est un nombre pteu
Line 1: Line 1:
  
-====== Programmation Shell =======+======Programmation Shell=======
  
-Les différents shells peuvent avoir des fonctions sensiblement différentes voir incompatibles. Ce n'est pas le cas pour la majorité d'entre elles. Ici nous parlerons de [[https://fr.wikipedia.org/wiki/Bourne-Again_shell|bash]] car c'est le plus couramment utilisé. Pour afficher la liste des options de bash il faut saisir ''bash -c "help set"''. Pour lire un script sans exécuter les commandes : ''bash -n''.+{{ :informatique:linux:bash_logo.png?300|}}
  
 +Les différents shells peuvent avoir des fonctions sensiblement différentes voir incompatibles. Ce n'est pas le cas pour la majorité d'entre elles. Ici nous parlerons de [[https://fr.wikipedia.org/wiki/Bourne-Again_shell|bash]] car c'est le plus couramment utilisé.
 +
 +Pour afficher la liste des options de bash il faut saisir ''bash -c "help set"''. Pour lire un script sans exécuter les commandes : ''bash -n''.
  
   * ''. <CONFIG_FILE>'' => permet de faire un //include// (notez bien le point + espace ". ")   * ''. <CONFIG_FILE>'' => permet de faire un //include// (notez bien le point + espace ". ")
-  * ''!!'' => est remplacé par la dernière commande (différent de ''$_'' qui contient uniquement le dernier paramètre de la dernière commande)+  * ''!!'' => est remplacé par la dernière commande (différent de ''$_'' qui désigne uniquement le dernier paramètre de la dernière commande)
 <code bash> <code bash>
 $ touch toto $ touch toto
Line 59: Line 62:
 echo ${VAR:=defaut}    # defaut (VAR prend également cette valeur) echo ${VAR:=defaut}    # defaut (VAR prend également cette valeur)
 </code> </code>
 +
 +=====Typage=====
 +
 +Il n'y a pas de typage strict en bash, toutes les variables sont considérées comme des chaînes de caractères, sur lesquelles on peut toutefois réaliser des opérations arithmétiques par exemple, si elles ne contiennent que des chiffres.
 +
 +Pour "émuler" une variable booléenne par exemple, il convient de tester son contenu puisque c'est en réalité une string :
 +<code bash>
 +is_ready=true   # is_ready est une string qui vaut "true"
 +if [ "$is_ready" = true ]
 +   then echo "I'm ready"
 +   else echo "I'm not"
 +fi
 +</code>
 +
 +Pour plus de détails sur le pseudo-typage en bash, voir la fonction [[informatique:linux:commandes_linux#declare|declare]].
  
 ===== Manipulation des variables===== ===== Manipulation des variables=====
Line 112: Line 130:
   * ''IFS="\n"'' (Internal Field Separator) le séparateur de champ est "ENTER" (utilisée par la commande read)   * ''IFS="\n"'' (Internal Field Separator) le séparateur de champ est "ENTER" (utilisée par la commande read)
   * ''$PWD'' renvoie le chemin du shell depuis lequel est lancé le script (équivalent à pwd) ; c'est complémentaire de ''$0''   * ''$PWD'' renvoie le chemin du shell depuis lequel est lancé le script (équivalent à pwd) ; c'est complémentaire de ''$0''
- 
  
  
Line 137: Line 154:
 trois trois
 </code> </code>
 +
 +Exemple de découpage d'une chaîne dans un tableau, avec comme séparateur ";" :
 +<code bash>
 +CHAINE='17;8 23;9'
 +IFS=";"                       # définition du séparateur
 +read -a TAB <<<"$CHAINE"
 +echo "${#TAB[@]}"              # affiche de la taille du tableau (nombre de cellule)
 + 3
 +printf '%s\n' "${TAB[@]}"      # affichage du contenu du tableau cellule par cellule
 + 17
 + 8 23
 + 9
 +</code>
 +
 ====Tableau à 2 dimensions==== ====Tableau à 2 dimensions====
  
-Ça n'eût pas existé pas sous bash :). Mais on peut l'émuler en créant un tableau associatif (qui, à une clé fait correspondre un contenu), en codant la clé pour émuler 2 dimensions. Exemple : pour émuler un tableau de 2 x 3 cases :+Ça n'eût pas existé sous bash :). Mais on peut l'émuler en créant un tableau associatif (qui, à une clé fait correspondre un contenu), en codant la clé pour émuler 2 dimensions. Exemple : pour émuler un tableau de 2 x 3 cases :
 <code bash> <code bash>
 # déclaration d'un tableau associatif T # déclaration d'un tableau associatif T
Line 161: Line 192:
 </code> </code>
  
 +====Tableau associatif====
  
 +Créer et utiliser un vrai tableau associatif :
 +<code bash>
 +declare -A TA=([cle1]=valeur1 ["cle 2"]="valeur 2" [cle3]=valeur3)
 +echo "${TA[cle1]}"
 +# valeur1
 +
 +# Parcourir le tableau
 +for cle in "${!TA[@]}"; do
 +   echo "cle=$cle ; val=${TA[$cle]}"
 +done
 +#cle=cle 2 ; val=valeur 2
 +#cle=cle3 ; val=valeur3
 +#cle=cle1 ; val=valeur1
 +</code>
 +
 +Pour connaitre la taille de ce tableau : ''${#TA[@]}'' (3 dans cet exemple).
 =====getopts : analyse des arguments d'un script===== =====getopts : analyse des arguments d'un script=====
  
Line 240: Line 288:
 </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======
Line 411: Line 529:
   * ''n1 -le n2'' plus petit ou égal   * ''n1 -le n2'' plus petit ou égal
  
 +Comme il n'y a pas de typage en bash, pour tester si la valeur d'une variable est un nombre (entier) il faut réaliser le tester :
 +<code bash>
 +# Solution à base de REGEX
 +[[ $VAR =~ ^[0-9]+$ ]] || echo "VAR n'est pas un entier"
 +# NB : l'expression régulière ne doit pas être quotée,
 +#      ou doit être enregistrée dans une variable sinon ça ne matche pas
 +
 +# "auto-test" numérique :)
 +[ $VAR -eq $VAR ] 2>/dev/null || echo "VAR n'est pas un entier"
 +</code>
 ==== Opérateurs ==== ==== Opérateurs ====
   * ''!'' unaire de négation   * ''!'' unaire de négation
informatique/linux/programmation_shell.txt · Last modified: 2023/10/02 13:35 by pteu