Atelier BASH pratique du vendredi 20 mars 2015 par PhilippeLhardy

BASH = Bourne Again SHell
Des lectures à conseiller :
Commande pour télécharger les dix exemples proposés par Philippe ;
Voir aussi cette page du blog de Philippe et nos archives de liste de diffusion:
Dans votre éditeur de textes préféré (gedit, nano, vim, emacs) recopier le script ci-dessous et sauvegarder le sous le nom :
  • scriptdephilippe.sh
Commande pour rendre un script (dont le nom est scriptdephilippe.sh) executable :
  • chmod u+rx scriptdephilippe.sh
Commande pour exécuter un script bash :
  • ./scriptdephilippe.sh

#!/bin/bash
# la ligne qui précède s'appelle le shebang 
# cette ligne ainsi que la précédente et la suivante sont des lignes de commentaires
# en revanche la ligne suivante n'est pas un commentaire
echo "Creation d'un tableau à l'aide d'une boucle for"
echo "on créé un tableau qui contient une table de 5 éléments (5 trucs) indexés" 
echo "depuis la position  0 jusqu'à la position 4."
declare -a tableau
for (( i=0 ; $i < 5 ; i++ ))
# oui les doubles parenthèses sont obligatoires 
do
    index=$(( i + 1 ))
    # oui la aussi les doubles parenthèses sont obligatoires 
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    tableau[$i]=$UNTRUC
done

taille_tableau=${#tableau[@]}
for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    echo "$(( i + 1 )): ${tableau[$i]}"
done

echo "Ex1 : transformez moi pour ne demander que 3 valeurs a lieu de 5."
# la réponse : il faut mettre 3 au lieu de 5 ici :
for (( i=0 ; $i < 3 ; i++ ))
do
    index=$(( i + 1 ))
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    if [[ $UNTRUC == "la solution est la ..." ]]
    then
	break
    else
	tableau[$i]=$UNTRUC
    fi
done

taille_tableau=${#tableau[@]}

for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    contenu=${tableau[$i]}
    echo "$(( i + 1 )): $contenu"
    if [[ "$toobad" == "stop" ]]
    then
	echo "Curieux, on aurait du s'arreter avant ..." >&2
    elif [[ "$contenu" == "STOP" ]]
    then
	echo "Curieux, on aurait du ne pas enregistrer cette valeur ..." >&2
	toobad=stop
    fi
done

echo "Transformez moi pour s'arreter de demander d'autres trucs si la réponse est 'STOP' et demander jusqu'à 20 trucs maximum."
echo "Mais pourquoi y a t'il des >&2 pour les Curieux ???"
echo "Qu'est ce qui va nous arreter ?"
read ARRET

# on créé un tableau qui contient une table d'élément indexé par position partant de 0.
declare -a tableau
#  20 max  : il faut mettre 20 au lieu de 3 ici :
for (( i=0 ; $i < 20 ; i++ ))
do
    index=$(( i + 1 ))
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    # etape 5 : il faut tester si UNTRUC vaut STOP ...
    if [[ $UNTRUC == "STOP" ]]
    then
	break
    else
	tableau[$i]=$UNTRUC
    fi
done

taille_tableau=${#tableau[@]}

for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    contenu=${tableau[$i]}
    echo "$(( i + 1 )): $contenu"
    if [[ "$toobad" == "stop" ]]
    then
	# les >&2 c'est pour écrire sur la sortie d'erreur et non sur la sortie standard.
	echo "Curieux, on aurait du s'arreter avant ..." >&2
    elif [[ "$contenu" == "$ARRET" ]]
    then
	echo "Curieux, on aurait du ne pas enregistrer cette valeur puisque c'est la valeur d'arret..." >&2
	toobad=stop
    fi
done

echo "Transformez moi pour s'arreter de demander d'autres trucs si la réponse est la même que la condition ARRET demandée au début."
echo "Qu'est ce qui va nous arreter ?"
read ARRET

# on créé un tableau qui contient une table d'élément indexé par position partant de 0.
declare -a tableau

for (( i=0 ; $i < 20 ; i++ ))
do
    index=$(( i + 1 ))
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    # etape 6 : il faut tester si UNTRUC vaut le contenu de ARRET :
    if [[ $UNTRUC == "$ARRET" ]]
    then
	break
    else
	tableau[$i]=$UNTRUC
    fi
done

taille_tableau=${#tableau[@]}
mon_fichier="oh_fichier"
echo "Oh le beau tableau qui va suivre" >$mon_fichier

for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    contenu=${tableau[$i]}
    echo "$(( i + 1 )): $contenu" $mon_fichier
    echo "$(( i + 1 )): $contenu" >>$mon_fichier
    if [[ "$toobad" == "stop" ]]
    then
	# les >&2 c'est pour écrire sur la sortie d'erreur et non sur la sortie standard.
	echo "Curieux, on aurait du s'arreter avant ..." >&2
    elif [[ "$contenu" == "$ARRET" ]]
    then
	echo "Curieux, on aurait du ne pas enregistrer cette valeur puisque c'est la valeur d'arret..." >&2
	toobad=stop
    fi
done

echo "Voici ce que contient $mon_fichier:"
cat $mon_fichier

echo
echo "Transformez moi pour sauvegarder le résultat dans un fichier nommé le_beau_fichier.txt"
echo "Tiens au passage pourquoi on utilise >$mon_fichier au début puis >>$mon_fichier dans la boucle ? Qu'est-ce qu'il se passe sinon"

# on a regroupé en fonction un ensemble d'actions en relation
echo "Des fonctions ..."
# on créé un tableau qui contient une table d'élément indexé par position partant de 0.
declare -a tableau

# on va pas dire que c'etait très compliqué ...
mon_fichier="le_beau_fichier.txt"

saisie()
{
echo "C'est quoi qui va nous arreter ?"
read ARRET

taille_tableau=${#tableau[@]}

for (( i=$taille_tableau ; $i < 20 ; i++ ))
do
    index=$(( i + 1 ))
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    # etape 6 : il faut tester si UNTRUC vaut le contenu de ARRET :
    if [[ $UNTRUC == "$ARRET" ]]
    then
	break
    else
	tableau[$i]=$UNTRUC
    fi
done
}

sauvegarde()
{
taille_tableau=${#tableau[@]}

# >$mon_fichier créé un nouveau fichier
echo "Oh le beau tableau qui va suivre" >$mon_fichier

for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    contenu=${tableau[$i]}
    echo "$(( i + 1 )): $contenu"
    # >>$mon_fichier ( notez les deux > ) ajoute à la fin du fichier existant
    echo "$(( i + 1 )): $contenu" >>$mon_fichier
    if [[ "$toobad" == "stop" ]]
    then
	# les >&2 c'est pour écrire sur la sortie d'erreur et non sur la sortie standard.
	echo "Curieux, on aurait du s'arreter avant ..." >&2
    elif [[ "$contenu" == "$ARRET" ]]
    then
	echo "Curieux, on aurait du ne pas enregistrer cette valeur puisque c'est la valeur d'arret..." >&2
	toobad=stop
    fi
done
}

lecture()
{
    while read INDEX_UNTRUC
    do
	if [[ $INDEX_UNTRUC =~ [0-9]*:\ (.*) ]]
	then
	    UNTRUC=${BASH_REMATCH[1]}
	    tableau[${#tableau[@]}]=$UNTRUC
	fi
    done < $mon_fichier
}

# vraiment cette solution c'est sans commentaire !
# lecture
saisie
sauvegarde

echo "Voici ce que contient $mon_fichier:"
cat $mon_fichier
echo "Transformez moi pour lire la liste précédente depuis le_beau_fichier.txt avant la saisie"

echo "A quoi peut bien servir le =~ dans la fonction de lecture ?"

# on a regroupé en fonction un ensemble d'actions en relation

echo "Des fonctions ..."

# on créé un tableau qui contient une table d'élément indexé par position partant de 0.
declare -a tableau

# on va pas dire que c'etait très compliqué ...
mon_fichier="le_beau_fichier.txt"

saisie()
{

    debut=$1
    
echo "Qu'est ce qui va nous arreter ?"
read ARRET

taille_tableau=${#tableau[@]}

if [[ $debut > $taille_tableau ]]
then
    debut=$taille_tableau
fi

for (( i=$debut ; $i < 20 ; i++ ))
do
    index=$(( i + 1 ))
    echo "Tapez un truc pour voir... ($index)"
    read UNTRUC
    echo "$index) $UNTRUC"
    # etape 6 : il faut tester si UNTRUC vaut le contenu de ARRET :
    if [[ $UNTRUC == "$ARRET" ]]
    then
	break
    else
	tableau[$i]=$UNTRUC
    fi
done
}

sauvegarde()
{
taille_tableau=${#tableau[@]}

# >$mon_fichier créé un nouveau fichier
echo "Oh le beau tableau qui va suivre" >$mon_fichier

for (( i=0 ; $i < $taille_tableau ; i++ ))
do
    contenu=${tableau[$i]}
    echo "$(( i + 1 )): $contenu"
    # >>$mon_fichier ( notez les deux > ) ajoute à la fin du fichier existant
    echo "$(( i + 1 )): $contenu" >>$mon_fichier
    if [[ "$toobad" == "stop" ]]
    then
	# les >&2 c'est pour écrire sur la sortie d'erreur et non sur la sortie standard.
	echo "Curieux, on aurait du s'arreter avant ..." >&2
    elif [[ "$contenu" == "$ARRET" ]]
    then
	echo "Curieux, on aurait du ne pas enregistrer cette valeur puisque c'est la valeur d'arret..." >&2
	toobad=stop
    fi
done
}

lecture()
{
    while read INDEX_UNTRUC
    do
	# Ah la beauté des expressions régulières qui ne s'appellent pas du tout comme ça en français, mais les informaticiens s'en fichent.
	# VARIABLE =~ regexp la VARIABLE a une suite de caractères qui peuvent se définir comme la regexp est écrite.
	# ici on extrait l'index avant les ':' car ce sont des nombres, et après le : il y a un espace ( que l'on 'échappe' par un \ ) puis on capture tout ce qui reste.
	if [[ $INDEX_UNTRUC =~ [0-9]*:\ (.*) ]]
	then
	    # Oui BASH_REMATCH est un bashisme et est le résultat du =~ (.*) précédent, il contient ... le reste...
	    UNTRUC=${BASH_REMATCH[1]}
	    tableau[${#tableau[@]}]=$UNTRUC
	fi
    done < $mon_fichier
}

# le # indique un commentaire..., un commentaire est ignoré par bash mais très instructif pour ... nous les humains.
lecture

# maintenant on commence à partir de la fin ...
taille_tableau=${#tableau[@]}
saisie $taille_tableau
sauvegarde

echo "Voici ce que contient $mon_fichier:"
cat $mon_fichier

echo "Et si on décidait à partir de quel index on réécrit sur le fichier existant plutôt que de rajouter de la fin ?"