This is an old revision of the document!
Table of Contents
programmation langage bash shell
Programmation Shell
. <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)
$ touch toto $ echo !! echo touch toto touch toto
Les variables
En bash, chaque variable est précédée de $
. On affecte un contenu ainsi : VAR=“toto”
et on récupère le contenu en ajoutant $
devant.
NOM="robert" echo "Salut, je suis le gros $NOM"
On peut les manipuler sans les déclarer proprement au préalable ; mais on peut être clean et les définir (declare VAR
) ou les supprimer (unset VAR
).
Tests de définition
Pour tester si une variable est non définie : ${VAR?message d'erreur}
ou vide : ${VAR:?message d'erreur}
.
unset VAR ${VAR?var non def} # -bash: VAR: variable non def (sur stderr) declare VAR ${VAR?var non def} # -bash: VAR: variable non def (sur stderr) VAR= ${VAR?var non def} # (rien car VAR est définie) ${VAR:?vide} # -bash: VAR: vide (sur stderr)
Pour utiliser une valeur par défaut au cas ou la variable n'est pas définie : ${VAR-non-def}
; on peut également vérifier si cette dernière est non nulle (non-vide) : ${VAR:-non-def}
.
declare VAR echo ${VAR-defaut} # (vide car VAR est définie) echo ${VAR:-defaut} # vide unset VAR echo ${VAR-defaut} # defaut echo ${VAR:-defaut} # defaut
Cela ne définit ni n'affecte VAR ; pour cela il faut utiliser la syntaxe ${VAR=defaut}
et ${VAR:=defaut}
.
declare VAR echo ${VAR=defaut} # (ne produit rien) echo ${VAR:=defaut} # defaut (VAR prend également cette valeur)
Manipulation des variables
${#VAR}
renvoie la longueur de la variable VAR. Si VAR est un tableau :${#VAR[@]}
${VAR}
permet de délimiter le nom de variable ; c'est utile dans le cas suivant par exemple :
scp user@server:/tmp/fic.txt ${REP_LOCAL}_/
Sans les {}
, l'interpréteur présumera que la variable se nomme $REP_LOCAL_
et non $REP_LOCAL
.
- on peut tronquer une variable :
${VAR:POS}
⇒ renvoie le contenu à partir de la position POS (comptabilisée à partir de 0). Si POS est négative (il faut la mettre entre parenthèses), on compte à partir de la fin de la chaine. ${VAR:POS:LONG}
: renvoie la sous-chaine de longueur LONG à partir de la position POS5e lettre
VAR=undeuxtroisquatre echo ${VAR:2} # deuxtroisquatre echo ${VAR:(-6)} # quatre echo ${VAR:(-6):2} # qu
On peut utiliser des motifs (qui en ont l'aspect mais ne sont pas exactement des expressions régulières) pour substituer des bouts de chaine :
${VAR#PAT}
: supprime la plus courte chaine répondant à la pattern PAT ; on peut partir de la fin de la chaine avec%
à la place de#
${VAR##PAT}
: supprime la plus longue chaine répondant à la pattern PAT (idem :%%
)${VAR/PAT/SUBST}
pour remplacer par SUBST la première occurrence du contenu de VAR répondant à la pattern PAT ; respectivement//
pour toutes les occurrences. On peut partir du début#
(par défaut) ou de la fin de la chaine%
, mais c'est dans tous les cas le motif le plus grand qui sera remplacer (pas de##
ni%%
).
VAR=undeuxtroisquatre echo ${VAR#u*e} # uxtroisquatre echo ${VAR##u*e} # (rien !) echo ${VAR%u*e} # undeuxtroisq echo ${VAR/trois/3} # undeux3quatre echo ${VAR//e/E} # undEuxtroisquatrE
source : https://www.patpro.net/blog/index.php/2006/04/07/20-manipulations-sur-les-variables-dans-bash/
Variables spécifiques
Ce sont des variables liées au contexte du script.
$0
est le nom du script$1 $2 … $10
les arguments du script. On peut les décaler grâce à la commandeshift
($2 devient $1, $3 devient $2, etc)$_
renvoie le dernier argument de la dernière commande$*
liste de tous les arguments$@
liste de tous les arguments (équivalent à$*
)$#
renvoie le nombre d'argument du script$$
renvoie le PID du script courant$!
renvoie le PID de la dernière commande$?
renvoie le retour (code d'erreur par exemple) de la dernière commande
IFS=“\n”
(Internal Field Separator) le séparateur de champ est “ENTER” (utilisée par la commande read)
Les tableaux
Les enregistrements commencent à l'index 0. Ainsi pour récupérer le contenu de la 5ème case on doit taper dans l'index 4.
TAB=( un deux trois )
: définition d'un tableau de 3 casesTAB[0]=val
: affectation du premier enregistrement du tableau TAB${TAB[0]}
: contenu du premier enregistrement du tableau TAB$TAB
: équivalent de${TAB[0]}
${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 #
:
- longueur de la 3e case :
${#TAB[2]}
- taille du tableau (nombre de case de celui-ci) :
${#TAB[*]}
(ou${#TAB[@]}
)
Les fonctions
read
read toto
permet de demander une saisie clavier à l'utilisateur.
Pour afficher un texte avant la saisie on utilise -p ; et on peut récupérer plusieurs saisie d'un seul coup :
read -p "Quel est le nombre indique sur votre CB ? Et le cryptogramme visuel de derriere ?" CARD_NUMBER CRYPTO
Expressions arithmétiques
Pour faire un calcul il faut l'encadrer de $((calcul))
ou $[calcul]
echo 1+1=$((1+1))
La fonction puissance s'écrit **
:
echo 2^5=$((2**5))
Pour incrémenter une variable : plusieurs possibilités :
z=`expr $z + 1`
z=$(($z+1))
z=$((z+1))
(entre doubles parenthèses, le $ est optionnel)(( z += 1 ))
Instructions conditionnelles
if
test expr
ou
if [ expr ] then else fi
- Exemple sur une seule ligne (-n renvoie TRUE si la chaine n'est pas vide) :
if [ -n "" ]; then echo "1"; else echo "0"; fi 0
Conditions multiples
Pour tester des conditions multiples, on doit encadrer les tests avec un double crochet :
if [[ TRUE && TRUE || FALSE ]] then echo "TRUE" else echo "TRUE QUAND MÊME !" fi
On peut également procéder ainsi :
if [ TRUE ] && [ TRUE ] || [ FALSE ]
Les conditions multiples sans parenthèses sont lues dans l'ordre d'apparition (de gauche à droite), ici cela équivaut à : (TRUE ET TRUE) OU FALSE
. Donc TRUE quand même.
- Structure avec “elif” (“elseif” dans d'autres langages) qui permet de faire des tests à la suite :
if [ expr ] then elif then elif then [..] else fi
Expression sur les fichiers
-d file
: existe et est un répertoire-e file
: existe-f file
: existe et non répertoire-h file
: si le fichier est un lien symbolique-s file
: existe et est de taille non nulle-r file
: existe et droit en lecture-w file
: existe et droit en écriture-x file
: existe et droit d'exécution-O file
: si le fichier nous appartient-G file
: si le fichier appartient à notre groupe
Chaînes de caractères
str1 = str2
str1 != str2
-z str
: vrai si chaîne de longueur nulle-n str
: vrai si chaîne de longueur non nulle
Nombres, comparaison
n1 -eq n2
égauxn1 -ne n2
non égauxn1 -gt n2
plus grand quen1 -ge n2
plus grand ou égaln1 -lt n2
plus petit quen1 -le n2
plus petit ou égal
Opérateurs
!
unaire de négation-a
et logique-o
ou logique( expr )
paranthésage\( et \)
sinon interprétées par le shell
case
Test plusieurs valeurs de <chaîne> (~ifs imbriqués).
case <chaîne> in motif1) echo "motif 1" echo "C'est le premier !!" ;; motif2|motif3) echo "motif 2 ou motif 3" ;; motif*) echo "tous les autres motifs" ;; *) echo "Tout le reste" ;; esac
for
Permet de créer une boucle déterministe : pour chaque valeur de i, on exécute la boucle.
Exemples :
for (( i = 1; i <= 5; i++ )) do echo -n "$i " done
Affichera : 1 2 3 4 5
.
Cela équivaut à : for i in {1..5}
qui est une autre façon d'incrémenter i de 1 à 5.
On peut aussi lui fournir une liste de mots :
for i in serveur1 serveur2 serveur3 do ssh $i "(uname -r)" done
On peut l'exécuter sur une seule ligne de commande en respectant cette syntaxe :
for i in serveur1 serveur2 serveur3; do ssh $i "(uname -r)"; done
break
Pour sortir prématurément d'une boucle for, while ou repeat, on utilise le mot-clé break :
for i in {1..5} do if [ $i -eq 3 ] then echo "Huston nous avons un probleme !" break fi echo $i done
Ce qui donne :
1 2 Huston nous avons un probleme !
continue
Pour sortir de l'occurrence courante de la boucle, on utilise continue. On quitte l'occurrence courante et on passe à la suivante :
for i in {1..5} do if [ $i -eq 3 ] then echo "Huston nous avons un probleme !" continue fi echo $i done
Ce qui donne :
1 2 Huston nous avons un probleme ! 4 5
while
Exécute la boucle tant que la condition suivant l'instruction while est remplie :
exemple : lire un fichier ligne par ligne
while read line do echo $line done < fic.txt
ou sur une seule ligne :
while read n; do echo $line; done < fic.txt
until
Exécute la boucle jusqu'à ce que la condition soit remplie :
until <condition> do echo "Toujours pas !" done
select
Permet de créer un menu interactif, c'est à dire une saisie utilisateur ;
- $PS3 permet de définir le prompt
- $REPLY contient l'index de la réponse
PS3="Prompt du menu" select i in {2..5} do # $REPLY contient l'index de la réponse ; # $i contient la valeur correspondante echo $REPLY-$i # pour sortir du menu (car il s'agit d'une boucle) break done
Divers
en vrac
- commande rsh
rsh -4 -n $serveur $commande >/dev/null 2>&1
- commande ping limitée à 3 envois avec un timeout de 0.05s
ping -c3 -w 0.05 soekris-${cpt} >/dev/null 2>&1 retour=$?
- attente d'un
SIGUSR1
(30) pour terminer le script :
trap "echo 'Exiting..' ; exit 0" 30
Substitution de chaine
Pour n'afficher qu'une partie d'une chaine (une sous-chaine donc), on utilise la syntaxe ${tst:<offset>:<length>}
.
L'offset, c'est l'origine (elle commence à 0 pour le premier caractère, comme souvent en informatique), et length c'est le longueur de la chaine affichée (facultative si on veut afficher jusqu'à la fin).
Par exemple :
TEST="Je suis chanceux" # on affiche la sous-chaine à partir du caractère n°3 (soit le 4ème caractère) : echo ${TEST:3} suis chanceux # idem, mais on se limite à 4 caractères affichés : echo ${TEST:3:4} suis # on peut spécifier un offset négatif pour compter l'offset à partir de la fin de la chaîne # cependant il faudra ajouter un espace avant le "-" (ou l'encadrer de parenthèses) echo ${TEST: -8} chanceux echo ${TEST:(-8)} chanceux
Remplacement de chaine
Syntaxe : ${<parameter>/<pattern>/<string>}
<parameter> c'est la chaine d'origine, <pattern> l'expression de la chaine recherchée, et <string> la chaine de remplacement.
<pattern> peut commencer par ces caractères spéciaux (à défaut, il ne remplace que la première occurrence rencontrée) :
/
pour rechercher toute les occurrences#
pour rechercher une chaîne qui commence par%
pour rechercher une chaîne qui se termine par
TEST="toto titi tata" # remplacer tous les "a" par des "i" echo ${TEST//a/i} toto titi titi # ne remplacer que "a" de fin de chaîne echo ${TEST/%a/i} toto titi tati # ne remplacer que le premier "t", par un "p" echo ${TEST/#t/p} poto titi tata
Modifier la casse
Pour modifier la casse, on utilise la syntaxe :
${parameter^pattern}
pour passer de minuscules à majuscules- ou
${parameter,pattern}
pour passer de majuscules à minuscules
<pattern> étant optionnel, auquel cas seule la première lettre sera prise en compte :
TEST="toto TITI tata" echo ${TEST^} Toto TITI tata
On peut doubler les lettres pour traiter toute la chaine de caractère :
echo ${TEST^^} TOTO TITI TATA echo ${TEST,,} toto titi tata
Enfin, on peut spécifier la pattern à la suite :
# on UPPERCASE tous les "t" echo ${TEST^^t} ToTo TITI TaTa # on UPPERCASE les "t" et les "a" echo ${TEST^^[ta]} ToTo TITI TATA
Préfixes et suffixes
Syntaxe : ${<parameter>#<word>}
pour les préfixes, ${<parameter>%<word>}
pour les suffixes, ce qui va supprimer la plus courte occurrence de la chaîne. Pour supprimer la plus longue occurrence, on utilisera respectivement ##
et %%
.
On s'en sert souvent pour manipuler les chemins et les noms de fichier :
FIC=/chemin/ve.rs/mon/fichier.ext # afficher uniquement son extension # (on supprime le plus long préfixe se terminant par ".") echo ${FIC##*.} fichier.ext # afficher le chemin du fichier : # (on supprime le suffixe le plus court contenant un "/") echo ${FIC%/*} /chemin/ve.rs/mon