======Script bash : variables, arguments, paramètres ====== * Objet : Script bash : variables, arguments, paramètres * Niveau requis : {{tag>débutant avisé}} * Commentaires : FIXME * Débutant, à savoir : [[:doc:systeme:commandes:le_debianiste_qui_papillonne|Utiliser GNU/Linux en ligne de commande, tout commence là !.]] :-) * Suivi : * Création par [[user>Hypathie]] le 18/03/2014 * Testé par [[user>Hypathie]] Juin 2014 * Commentaires sur le forum : [[https://debian-facile.org/viewtopic.php?pid=142041#p142041| Lien vers le forum concernant ce tuto]] ((N'hésitez pas à y faire part de vos remarques, succès, améliorations ou échecs !)) Contributeurs, les FIXME sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli ! **Nota : Les autres wiki :** * [[doc:programmation:shells:debuter-avec-les-scripts-shell-bash | debuter-avec-les-scripts-shell-bash]] * ;-) * [[doc:programmation:shells:script-bash-detail-sur-les-parametres-et-les-boucles | modification de variable et de paramètre]] * [[doc:programmation:shells:script-bash-enchainement-de-commandes-et-etat-de-sortie|script-bash-enchainement-de-commandes-et-etat-de-sortie]] * [[doc:programmation:shells:script-bash-etat-de-sorie-et-les-tests|script-bash-etat-de-sortie-et-les-tests]] * [[doc:programmation:shells:tableaux|script-bash-les-tableaux]] * [[doc:programmation:shells:fonction|script-bash-les-fonctions]] ===== Création, suppression, exportation de variables ===== Le nom d'une variable est un simple pointeur vers l'emplacement mémoire où sont conservées les données qu'elle contient.\\ Les variables qu'on crée dans un script (ou dans le terminal) sont localisées dans ce script (ou à l'ouverture d'un terminal) c'est-à-dire qu'elles ne sont utilisables que lorsqu'on exécute son script, (ou que l'on appelle la valeur d'une variable qu'on vient de déclarer dans un terminal). Et il s'agit du script d'un utilisateur, il faut les distinguer [[doc:programmation:shells:la-page-man-bash-les-caracteres-speciaux#caracteres-des-variables-de-substitution-predefinies|des variables de substitution prédéfinies]] et [[doc:programmation:shells:la-page-man-bash-les-caracteres-speciaux#appel-de-la-valeur-des-variables-d-environnement-predefinies|des variables d'environnement prédéfinies]]. Mais comment enregistrer une valeur en mémoire ?\\ C'est par exemple, l'affectation d'une valeur au nom d'une variable qui va permettre d'enregistrer en mémoire cette variable avec sa valeur\\ Avant tout prenez bien conscience que la déclaration d'une variable n'est pas confinée au script, mais qu'il est possible de déclarer une variable dans le shell courant (dans le terminal). Voir absolument : [[doc:programmation:shells:la-page-man-bash-les-caracteres-speciaux#details-sur-le-caractere|détail sur le caractère $]]. **Voyons d'abord comment créer une variable de cette manière et comment utiliser sa valeur.** ;-) ==== Affectation directe : ==== La déclaration d'une variable se fait lors de son affectation, c'est-à-dire lorsqu'on assigne au nom de la variable une valeur au moyen du caractère = (sans espace avant et après). #!/bin/bash nom_de_la_variable=ValeurDeLaVariable >La valeur ''ValeurDeLaVariable'' a été mémorisée. ===$nom_de_la_variable=== Pour "utiliser" une variable, on se sert de sa valeur : il faut donc appeler sa valeur et cela se fait avec le caractère spécial ''$'' accolé au nom de la variable : #!/bin/bash nx_fichier=les-fonctions touch ~/$nx_fichier ls -la ~/$nx_fichier >Les programmes (ou commandes) ''touch'' et ''ls'' ont utilisé la valeur de > >la fonction nommée ''nx_fichier'', dont la valeur correspond à la chaîne > >de caractères ''les_fonctions''. ===Une variable n'est pas typée=== La valeur d'une variable peut être un nombre, un ou plusieurs caractères, du texte espacé, une commande, la valeur d'une variable. #!/bin/bash var1=a var2=texte var3="texte avec espaces" var4=55 var5=$var1 #ici on affecte à la variable var5, la valeur de la variable var1 var6=$0 #ici on affecte à la variable var6, la valeur de la variable pré-définie $0 (1) echo -e "valeur de var1: $var1\nvaleur de var2: $var2\nvaleur de var3: $var3\nvaleur de var3: $var4\nvaleur de var5: $var5\nvar6: $var6" >(1) $0 a pour valeur pré-définie le nom du programme valeur de var1: a valeur de var2: texte valeur de var3: texte avec espaces valeur de var3: 55 valeur de var5: a var6: /home/hypathie/MesScripts/mon-script ===Déclaration de plusieurs variables sur une ligne=== On peut déclarer plusieurs variables sur une même ligne, il suffit pour cela de mettre un espace entre chacune : #!/bin/bash set -o posix var1=a var2=texte var3="texte avec espaces" var4=55 var5=$var1 var6=$0 /bin/echo -e "valeur de var1: $var1\nvaleur de var2: $var2\nvaleur de var3: $var3\nvaleur de var3: $var4\nvaleur de var5: $var5\nvar6: $var6" # même retour que précédemment Le __nom d'une variable__ peut être composé : * par des lettres de a-z ou de A-Z ; * par des chiffres de 0-9 . * Il peut contenir un underscore ''_''. Mais il ne doit jamais : * commencer par un nombre ; * par underscore ; * un caractère spécial ; * ni être un mélange de lettres minuscules et majuscules. * Voir [[http://abs.traduc.org/abs-fr/ch04s02.html|l'exemple 4.3. Affectation de variable, basique et plus élaborée]] * Voir [[http://abs.traduc.org/abs-fr/ch04s03.html|Variable nulle et variable non-déclarée dans l'exemple]] Pour concaténer les valeurs deux variables : #!/bin/bash var1=lala var2=li var3=$var1$var2 echo $var3 ==== Affectation par la lecture : read ==== On peut créer des variables au moyen de commandes, comme par exemple la commande read qui est une commande interne (ou primitive) au shell. * Syntaxe : read nom_de_la_variable *La valeur est enregistrée par l'utilisateur sur l'entrée standard (i.e. ce qu'on écrit à l'invite de commande).\\ *Le nom de la variable s'écrit juste après read, ce n'est qu'un pointeur vers la valeur que vous avez rentrée. Par exemple dans un script : #!/bin/bash echo "Bonjour : qui êtes-vous ?" read nom echo "Enchanté $nom !" De même dans le terminal on peut tout à fait entrer tour à tour chacune des lignes de ce script, essayez ! ;-) * L'option -p permet d'insérer un message avant l'attente de la valeur que l'utilisateur doit entrer. #!/bin/bash read -p "entrez votre prénom: " prenom echo "bonjour $prenom !" >Ici ''prenom'' est le nom de la variable, et sa valeur est entrée par l'utilisateur depuis le terminal. > >Là aussi ces deux commandes peuvent être entrées dans le terminal. * ''read'' permet de déclarer plusieurs variables successivement (dans terminal ou script): read -p "entrez votre nom et prénom: " nom prenom entrez votre nom et prénom: >On entre par exemple les deux chaînes de caractères, ''debian'' et ''facile'', puis on peut récupérer la valeur de chacune des deux variables ''nom'' et ''prenom''. echo $prenom $nom facile debian Mais dans un script c'est plus rapide ! 8-) * read et variable non-déclarée #!/bin/bash read -p "entrez votre nom d'utilisateur: " echo "bonjour $USER !" >Ci-dessus, on n'a pas mis le ''nom'' de la variable, parce qu'on ne cherchera pas >à utiliser la valeur de cette variable. Cela permet au programme de se poursuivre. >Quand on entre dans le terminal la réponse attendu par ''read'', le retour de la >commande est ''0'', donc elle est considérée comme exécutée, et le shell passe à >l'exécution de la commande suivante. Quelques options utiles de la commande ''read''. * ''-p'' : afficher un message * ''-n'' : limiter le nombre de caractères * ''-t'' : limiter le temps autorisé pour saisir un message * ''-s'' : ne pas afficher le texte saisi On peut utiliser plusieurs options.\\ Par exemple: read -p "entrez votre année de naissance (deux derniers chiffres): " -n 2 annee ====Modification de la valeur d'une variable ==== Pour modifier la valeur d'une variable, il suffit de l'affecter d'une nouvelle valeur. #!/bin/bash var1=bonjour echo $var1 var1=23 echo $var1 var1= echo $var1 var1=Bonjour echo $var1 bonjour 23 Bonjour ====Protection de variable : "readonly" ==== On protège une variable avec la commande ''readonly''. La variable devient alors __une variable en lecture seule__. Cela lui donne la caractéristique d'être figée : on ne peut plus alors, au cours du même script, réaffectée par une nouvelle valeur une variable en lecture seule, y compris si cette variable a été déclarée nulle. #!/bin/bash var1=toto var2= echo "$var1 $var2" readonly var1 var2 var1=titi var2=titi unset var1 var2 toto ligne6: var1 : variable en lecture seule ligne7: var2 : variable en lecture seule ligne 8 : unset: var1 : « unset » impossible : variable est en lecture seule ligne 8 : unset: var2 : « unset » impossible : variable est en lecture seule ==== Suppression de variable : unset==== Soit le script "essai.sh" : passons à ce script l'argument ''vous'' #!/bin/bash var1=coucou var2=$1 echo "$var1 $var2" unset var2 echo "$var1 $var2" var1=$1 var2=vous echo "$var1 $var2" unset var2 echo "$var1 $var2" #!/bin/bash var1=yep var2=coucou echo "$var1 $var2" unset var2 echo "$var1 $var2" echo " " echo "mais pour un paramètre :" echo " " var1=yep var2=coucou var3=$1 echo "$var1 $var2 $var3" unset var2 var3 echo "$var1 $var2 $var3" var2= var3=$1 echo "$var1 $var2 $var3" yep coucou yep mais pour un paramètre : yep coucou yep yep ==== Exportation de la valeur d'une variable==== === Définition === Exporter la valeur d'une variable signifie que l'on envoie à un processus fils, la valeur d'une variable depuis un processus père. Un processus, c'est un programme en cours d'exécution, mais aussi son environnement d'exécution.\\ Ainsi le shell qui lance un script est le processus père du script lancé. Sur la notion de processus voir [[doc:programmation:shells:bash-les-differents-caracteres-speciaux?&#notion-de-processus|Notion de processus]] === Exemple === On peut exporter depuis le terminal, une valeur pour remplacer provisoirement une variable d'un script. Coucou="Bonjour" >On déclare la variable ''Coucou'', affectée de la valeur ''Bonjour'' depuis le terminal. > >Le shell courant l'a enregistré. echo 'echo "Coucou=$Coucou"' > test.sh >Là, on crée le fichier "test.sh" contenant la ligne : '' echo "Coucou=$Coucou" ''. > >Il contient une variable, de même nom que celle, précédemment déclarée et affectée de la valeur ''Bonjour'' depuis le terminal. chmod u+x test.sh >Le fichier "test.sh" devient exécutable pour l'utilisateur principal. export Coucou >On exporte la variable ''Coucou''((Il s'agit ben sûr, de celle déclarée dans le terminal au début de l'exemple)). > >Attention, ce n'est jamais la __valeur__ d'une variable que l'on exporte ! ./test.sh Coucou="Bonjour" >Il faut que le script déclare une variable de même nom (''Coucou= '') ; qu'il récupère celle exportée depuis le terminal (''$Coucou'') ; et bien évidemment, qu'il affiche (''echo'') tout cela :( ''echo "Coucou=$Coucou" ''). >Dans ces conditions, la valeur de la variable ''Coucou'' une fois exportée, peut valoir pour la variable du script "test.sh" qui est le __processus fils__ du shell courant. >Mais une fois __le terminal réinitialisé__, si on lance ./test.sh, ce script est le >processus fils d'un "nouveau" processus père (= le nouveau terminal) qui n'a plus > en mémoire la valeur ''Bonjour'' pour la variable nulle ''Coucou'' du script. >Et dans ce cas : ./test.sh Coucou= __Pour réinitialiser son terminal__,\\ il suffit de fermer et de le ré-ouvrir\\ ou de recharger son fichier ~/.bashrc : source ~/.bashrc ou . ~/.bashrc =====Quand les valeurs sont des paramètres ===== On peut considérer que les termes paramètre et argument sont synonymes.\\ Le terme paramètre de position, renvoie à l'appel de la valeur des paramètres (ou arguments) passés au script. ====Utiliser des paramètres de positions ==== Lorsqu'on ajoute un argument au script avant son exécution, on peut alors récupérer la valeur de ce paramètre.\\ * Pour récupérer chaque paramètre : $1 ; $2 ; $3 etc. * Pour récupérer tous les paramètres : $@ * Pour récupérer le nombre de paramètres passés au script : $# * Pour récupérer la dernière commande : $? (Par défaut, 0 quand tout s'est bien passé, 1 quand il y a une erreur, sinon on fait exit xx, $? affiche xx) EXEMPLES : soit le script "essai.sh" #!/bin/bash var=Bonjour echo $var echo "$1" echo "$2" echo "$3" echo "ou le paramètre 1 est: $1, le deuxième est: $2, le troisième est : $3" echo " " echo "tous les paramètres $@" ./essai.sh a b c Bonjour # on peut récupérer une valeur (ou des valeurs) déclarée(s) et les paramètres de position a b c ou le paramètre 1 est: a, le deuxième est: b, le troisième est : c tous les paramètres a b c * Tous les arguments passés au scripts $* et $@ sont synonymes #!/bin/bash echo $1 echo $* echo $@ echo $# ./essai.sh bonjour à tous bonjour bonjour à tous bonjour à tous 3 * Là de même pour $* et $@ : #!/bin/bash echo $1 echo $* echo $@ echo $# ./essai.sh "bonjour à tous" bonjour à tous bonjour à tous bonjour à tous 1 * Mais avec la commande set qui modifie provisoirement les paramètres : Pour plus de détails sur la commande set voir : [[doc:programmation:shells:script-bash-detail-sur-les-parametres-et-les-boucles?&#syntaxe-de-set]] #!/bin/bash set "bonjour à tous" echo $* echo $@ echo $1 echo $# ./essai.sh bonjour à tous bonjour à tous bonjour à tous 1 * Ou encore : #!/bin/bash set bonjour à tous echo $* echo $@ echo $1 echo $# ./essai.sh bonjour à tous bonjour à tous bonjour 3 #! /bin/bash Nombre_arguments_attendus=1 if [ $# -ne $Nombre_arguments_attendus ]; then echo "Le nombre d'arguments est invalide : $#" echo "Nombre argument attendu : ${Nombre_arguments_attendus} " fi #if [ "$#" -ne 1 ]; then # echo "Le nombre d'arguments est invalide" #fi echo "Script Started !" ./essai.sh Script Started ! =====Récupérer la longueur d'une valeur de variable===== * Pour obtenir la longueur d'une chaîne stockée dans une variable, on écrit ''${#VAR}''. Exemples : #!/bin/bash var="j'aime debian-facile" echo ${#var} * Pour récupérer la longueur d'un paramètre de position : FIXME =====Substitutions de commande===== ===Utilisation === Permet de se servir de la sortie d'une commande dans un autre contexte pour ; - affecter cette sortie à une variable ; - utiliser cette sortie comme argument d'une autre commande - etc. ===Deux syntaxes :=== `commande` OU $(commande) ====Substitution simple : $(commande)==== #!/bin/bash dir=$(pwd) echo "mon répertoire est : $dir" mon répertoire est : /home/hypathie *plusieurs commandes: #!/bin/bash echo $(pwd ; ls) ====Imbrication de commandes : $(cmd $(cmd))==== echo $( ls $(pwd)/Documents) === Imbrication avec ''set'' === #!/bin/bash set $(pwd ; whoami) echo "$1 : $2" echo $# Ou #!/bin/bash set -- $(ls -l $(pwd)/.bashrc) echo $* =====Typologie des variables ===== Comme nous l'avons vu on peut affecter une variable par différents types de valeurs ; des chaînes de caractères, des nombres, des valeurs d'autres variables, des substitutions de commandes.\\ On dit pour cela qu'en bash les variables ne sont pas typées.\\ Mais il peut être intéressant de typer une variable. Pour ce faire, il faut utiliser des commandes internes à bash qui permettent de déclarer une variable typée.\\ ====declare et typeset ==== ^ commandes ^options ^ |declare/typeset |''-r'' : lecture seule | |declare/typeset |''-i'' : entier | |declare/typeset |''-a'' tableau (array) | |declare/typeset |''-f'' : fonction(s) | |declare/typeset |''-x'' : export | |declare/typeset |''-x'' : ''var=$valeur'' | Voir : [[http://abs.traduc.org/abs-5.1-fr/ch09s04.html|Guide avancé d'écriture des scripts Bash: 9.4. Typer des variables : declare ou typeset]] ===Remarques sur la commande "declare" et les calculs === **Méthode non POSIX**\\ * La valeur d'une variable peut être une expression arithmétique, pour initialiser une variable de type entier on utilise l'option ''-i'' de la commande ''declare'' :\\ ''declare -i nom[=expression] ...'' #!/bin/bash declare -i x=35*2 echo $x retour 70 * Pour que la valeur d'une variable ne soit pas accidentellement modifier, il faut ajouter l'attribut ''-r''. #!/bin/bash declare -ir a=35*2 declare -ir b=5+5 echo $(($a+$b)) 80 ===== Variables numériques et calculs ===== ==== Les variables typées pour les calculs : let ou (( ... )) ==== Voir : [[doc:programmation:shells:page-man-bash-iv-symboles-dans-les-calculs-mathematiques?&#operateurs-arithmetiques|les opérateurs arithmétiques]] ===Syntaxe=== let 'var = 5 + 5' OU LE SHELL ARITHMÉTIQUE : $(( 5 * 3 )) === Exemples=== #!/bin/bash let "a = 10" let "b = 2" let "c = a+b" echo $c let "e = 10*2" echo $e let "f = 15" let "f *=2" echo $f echo " " let 'var = 5 + 5' echo "$var" echo " " echo $(( 20 + 20 )) var1="2" var2="5" echo $(( $var2 % $var1 )) 12 20 30 10 40 1 ==== L'affectation arthmétique==== Voir [[doc:programmation:shells:page-man-bash-iv-symboles-dans-les-calculs-mathematiques?&#operateurs-d-affectation-arithmetique| les opérateurs d'affectation arithmétique]] Cela consiste à affecter à une variable le résultat d'un calcul arithmétique, par la __constante__ (donc avec ''let'') qu'on lui a donné.\\ Soit une variable var de valeur x, si l'on fait ''var +=2'' alors la variable var sera ''x + 2''.\\ >cela permet de faire des incrémentation par autre chose que 1.) >Il en va de même pour les autres opérateurs.\\ * Exemples let "a = 5" let "b = 10" let "c = a *= 3" let "d = a += 3" # valeur précédente de a conservée pour calculer d : 15+3 =18 let "e = b /= 3" let "f = b /= 3" # valeur précédente de b conservée pour calculer f : 3/3 =1 echo "c=$c d=$d e=$e f=$f" # réponse : c=15 d=18 e=3 f=1 i=1 let "i += 7" echo "i=$i" # réponse : i=8 j=4 let "j *= 5" echo "j=$j" # réponse : j=20 ===Incrémentation, décrémentation=== * incrémentation, décrémentation de la valeur 1 : ''(( var++ ))'' ; ''(( ++var ))'' ; ''(( var-- ))'', etc. #!/bin/bash let "var = 5" echo "$var" (( var++ )) echo "$var" (( var-- )) echo "$var" Retour : 5 6 5 * L'incrémentation se fait aussi sur une boucle ! #!/bin/bash i=1 # on initialise le compteur while [ $i -le 10 ]; do echo $i let $[ i+=1 ] # incremente i de 1 a chaque boucle done [[doc:programmation:bash:script:tableaux#se-creuser-un-peu-les-meninges|voir aussi ici]] La commande **$[**...**]** équivalente à la commande **$((**..**))** __**ne doit plus être utilisée**__.\\ \\ Pour des raisons de rétrocompatibilité, **$[**...**]** est toujours active dans nos interpréteurs actuels. Mais déjà, elle n'est plus documentée dans la page du manuel de bash.\\ ... Viendra, où **$[**...**]** **ne sera plus disponible**.\\ \\ La commande d'incrémentation **let $[ i+=1 ]** doit être écrite ainsi : **let i+=1** ou **let i++** ou **((i++))**. * Ou encore de cette manière : N=$(($N+1)) [[doc:programmation:shell:avancee#les-fonctions|voir ici le code complet de cet extrait]] ====Changements de bases ==== Bash permet de changer de base (Il est par défaut en base 10)\\ * base 8 (octal) : un chiffre n précédé de zéro : ''0n''\\ exemple : 02 => 2 en base 8 * base 16(hexadécimal): un chiffre n précédé de zéro+x : ''0xn''\\ exemple : 0x3 => 3 en base 16 * autres bases : ''base#nombre'' * base maximale : base 64 =====Références ===== [[doc:programmation:shell:shell#variables-et-environnement|Le shell pour tous : "Variables et environnement"]]\\ [[doc:programmation:shell:variables]]\\ [[http://abs.traduc.org/abs-fr/ch04.html|Guide avancé d'écriture des scripts Bash : Introduction aux variables et aux paramètres]] =====La suite c'est ici ===== [[doc:programmation:shells:script-bash-detail-sur-les-parametres-et-les-boucles|script-bash-detail-sur-les-parametres]]