reponse=42
On utilise le caractère $
echo $reponse
read nom_variable
L’utilisateur doit saisir une chaîne de caractères et terminer par la
touche Entrée
Affichage:
echo $nom_variable
Demande avec message:
$ read -p "saisir une valeur: " valeur
saisir une valeur: hello
$ echo $valeur
hello
Pour vérifier une condition avant d’exécuter une commande, on utilise la structure syntaxique suivante:
if CONDITION
then
COMMANDE
fi
#/bin/bash
if grep laurent /etc/passwd
then
echo OK
fi
fichier=/tmp
if [[ -e $fichier ]]
then
echo "le fichier existe"
fi
fichier=/tmp
if [[ ! -e $fichier ]]
then
echo "Le fichier n'existe pas"
fi
if CONDITION
then
COMMANDE_SI_CONDITION_VRAIE
else
COMMANDE_SI_CONDITION_FAUSSE
fi
#/bin/bash
if grep laurent /etc/passwd
then
echo OK
else
echo KO
fi
fichier=/tmp/nexistepas
if [[ -e $fichier ]]
then
echo "le fichier existe"
else
echo "Le fichier n'existe pas"
fi
La commande help test
donne tous les opérateurs
utilisables dans une condition de type [[ ... ]]
\
$ echo Des chose \
> sur plusieurs lignes
Des chose sur plusieurs lignes
#
# Ceci est un commentaire
echo "Message" # Ceci est aussi un commentaire
cat /etc/passwd |\
# Redirige cat vers grep
grep www-data
"
Citation partielle (ie interprétée)
$ echo "$reponse=.*"
42.*
'
Citation complète (non interprétée)
$ echo '$reponse=.*'
$reponse=.*
$ echo $'\n\nJe suis la dernière ligne'
Je suis la dernière ligne
$ echo '\n\nJe suis la dernière ligne'
;
Permet de mettre plusieurs commandes sur une même ligne
echo salut ; echo les gens
$ echo bonjour ; echo salut
bonjour
salut
$ for i in 1 2 3 ; do echo $i ; done
1
2
3
$ for i in 1 2 3 do echo $i ; done
bash: syntax error near unexpected token `done'
Astuce: Utiliser la combinaison de touches ctrlX puis ctrlE
ANSI-C Quoting (Bash Reference Manual)
:
: > un_fichier
: >> info_connexion
$ if [[ -f nexistepas ]] ; then
:
else
echo Aucun fichier
fi
Aucun fichier
L’intérêt de déclarer les variables est notamment
declare -i nombre
#!/bin/bash
set -euo pipefail
declare -i nombre
nombre=4
nombre=$nombre/2
echo "nombre = $nombre" # Affiche 2
# Non déclarée
autre=6
autre=$autre/2
echo "autre = $autre" # Affiche 6/2
#!/bin/bash
set -euo pipefail
declare -i nombre
# Tentative d'affectation d'une chaîne
nombre="quatre" # Erreur: unbound variable
declare -i x y z
Utilisation :
$ x=2
$ y=x+9
$ echo $y
11
readonly constante=1
declare -r constante=1
constante=3
Cette instruction instruction provoque une erreur:
constante: readonly variable
Déclaration d’une variable exportée:
declare -x variable_exportee
Voici un programme correctement déclaré:
#!/bin/bash
set -euo pipefail
echo $variable_exportee
echo "Fin du programme"
$ ./var_export
./var_export: line 4: variable_exportee: unbound variable
Si on exporte la variable depuis le Shell:
$ export variable_exportee=45
$ ./var_export
45
Fin du programme
Suppression de la variable exportée
unset variable_exportee
$ ./var_export
./var_export: line 4: variable_exportee: unbound variable
Ajout de la déclaration:
#!/bin/bash
set -euo pipefail
declare -x variable_exportee
echo $variable_exportee
echo "Fin du programme"
$ ./var_export
Fin du programme
declare -a fichiers
Créons un ensemble de fichiers:
$ touch {a..f}.txt
La bonne manière de définir le tableau avec l’expansion:
$ fichiers=(*)
0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
a.txt | b.txt | c.txt | d.txt | e.txt | f.txt |
Voir le paragraphe Mauvaise méthode d’affectation d’un tableau
$ fichiers=*
$ echo $fichiers
a.txt b.txt c.txt d.txt e.txt f.txt
Bien que cela ait semblé fonctionner, ce qui suit montre que ce n’est pas le cas:
$ echo "$fichiers"
*
$ echo "${fichiers[0]}"
*
$ echo "${fichiers[1]}"
$ echo "${fichiers[2]}"
$ echo "${fichiers[@]}" # Tous les éléments du tableau
*
$ echo "${fichiers[0]}"
a.txt
$ echo "${fichiers[1]}"
b.txt
$ echo "${fichiers[@]}" # Tous les éléments du tableau
a.txt b.txt c.txt d.txt e.txt f.txt
$ echo ${#fichiers[@]}
6
On utilise le symbole :
:
:
$ echo ${fichiers[@]:3:2}
d.txt e.txt
IFS
et les tableauxModifier cette variable permet de gérer correctement les noms de fichiers avec des espaces
La variable IFS
doit de préférence être déclarée comme
suit:
export IFS=$'\n\t'
for
for i in ${!fichiers[@]}
do
echo "fichiers[$i]: ${fichiers[$i]}"
done
for
for ((i=0; i<${#fichiers[@]}; i++))
do
echo "fichiers[$i]: ${fichiers[$i]}"
done
$*
et $@
$*
et $@
#!/bin/bash
echo "Using \"\$*\":"
for a in "$*"; do
echo $a;
done
echo -e "\nUsing \$*:"
for a in $*; do
echo $a;
done
echo -e "\nUsing \"\$@\":"
for a in "$@"; do
echo $a;
done
echo -e "\nUsing \$@:"
for a in $@; do
echo $a;
done
Ressources:
declare | grep nom_tableau
traiter_info(){
declare reference="${1}"
declare cible="${2}"
declare option="${3}"
if [[ -z "${reference}" ]] ; then
echo "Reference est vide"
echo "Envoi dans ${cible} sans référence avec ${option}"
else
echo "Envoi dans ${cible} depuis ${reference} avec ${option}"
fi
}
traiter_info "data123" "cible principale" "attention"
traiter_info "" "cible principale" "attention"
declare -f nExistePas > /dev/null || ( echo "Fonction nExistePas non déclarée" >&2 ; exit 2 )
traiter_info ()
{
declare reference="${1}";
declare cible="${2}";
declare option="${3}";
if [[ -z "${reference}" ]]; then
echo "Reference est vide";
echo "Envoi dans ${cible} sans référence avec ${option}";
else
echo "Envoi dans ${cible} depuis ${reference} avec ${option}";
fi
}
La portée d’une variable peut être réduite à la fonction dans laquelle elle est déclarée:
# Portée
portee_limitee(){
declare variable_locale="Je suis limitée"
}
portee_non_limitee(){
variable_locale_visible="Je suis accessible partout"
}
portee_limitee
portee_non_limitee
echo ${variable_locale_visible} # Affiche: Je suis accessible partout
echo ${variable_locale} # Erreur: variable_locale: unbound variable
Ceci est une pratique recommandée lors de l’utilisation de fonctions
declare -f
Il ne s’agit pas de déclaration ici mais d’une vérification
declare -f ma_fonction
Le code d’erreur renvoyé est