Dans le cadre de mes activités, j'ai écrit des scripts Shell ayant pour but de formater des chaînes de caractères à l'intérieur du script, je vous propose de les partager avec vous tout en introduisant des fonctions afin de vous faciliter la prise en main et la réutilisation.
N'étant pas expert du script Shell, tout commentaire est le bienvenu.
Les exemples de scripts donnés ci-après sont testés sous linux et hp-ux.
Le premier exemple étant simple, il prépare le second qui traite du formatage des chaînes. Ceux qui sont pressés peuvent juste jeter un œil sur la seconde partie de ce billet.
Fonction de lecture des arguments passés
Le premier script nommé tst1.sh a deux fonctions simples qui serviront à :
- Valider le nombre d'arguments attendus par le script. - Afficher ces arguments
Son contenu est comme suit:
#!/bin/sh scriptName=$(basename $0) syntaxe=" $scriptName value Exemple: $scriptName MY_VAL" nb_args_needed=1 # ----------------- DECLARER LES FONCTIONS ---------------------------- # declarer une fonction validateNumberArg() { if [ "$#" -lt $nb_args_needed ] then echo "Erreur: Arguments absents ou le nombre argument \"$#\" est insuffisant Syntaxe: $syntaxe" exit 1 fi } # declarer une fonction affichage arguments displayArguments() { echo "Nombres de paramètres : $#" for u in $@ do echo "$u" done } # ------- FIN DECLARATION DES FONCTIONS -------------------------- # *********************** **************** ********************************* # *********************** Debut du script ********************************* # *********************** ******************* ********************************* validateNumberArg $@ displayArguments $@
Le script peut être exécuté par:
./tst1.sh MAVALEUR
Ce script analyse le nombre d'arguments qui lui sont passés et s'il y en a moins de 2 il affiche la syntaxe d'utilisation et se termine.
Nous allons améliorer ce premier script afin de préciser davantage le format des arguments attendus et par conséquent mieux les récupérer.
#!/bin/sh scriptName=$(basename $0) syntaxe=" $scriptName -a value Exemple: $scriptName -a MAVALEUR" nb_args_needed=2 # déclaration dune fonction exemple displayArguments() { echo "Nombres de paramètres : $#" for u in $@ do echo "$u" done } # déclaration d'une fonction validateNumberArg() { if [ "$#" -lt $nb_args_needed ] then echo "Erreur: Arguments absents ou le nombre argument \"$#\" est insuffisant Syntaxe: $syntaxe" exit 1 fi } # lectureArguments necessite une variable Globale export MONARGUMENT="" lectureArguments() { while getopts "a:" OPTION do case $OPTION in a) MONARGUMENT=$OPTARG ;; :) echo "*** OPTION \"$OPTARG\" sans arg" exit 1 ;; \?) echo "*** OPTION \"$OPTARG\" inconnue !!!" exit 1 ;; esac done } # ***********************--- End Functions ---************************** # Controler le nombre d arguments passes au script validateNumberArg $@ # Call function lectureArguments lectureArguments $@ echo "monArgument: $MONARGUMENT "
Fonction de formatage des chaînes
Cette seconde partie présente un script permettant de formater les chaînes de caractères à l'intérieur du script.
Ce point est mal documenté sur le web à moins de recourir aux fonctionnalités awk, sed,..
La technique utilisée ici repose sur la redéfinition du séparateur IFS à traiter avec beaucoup de précaution.
C'est pour vous éviter des effets de bord que nous indiquons comment sauvegarder la valeur initiale d'IFS afin de la remettre en place aussitôt.
Ci-après quelques fonctions élémentaires qui permettent de réaliser des substitutions puis de formater la chaîne de la manière suivante:
Nous récupérons la valeur de l'argument du script qui peut être une liste de codes départements séparée par une virgule. Pour fixer les idées, on suppose que le script est lancé avec la ligne suivante:
./tst2.sh -a 75,76,89
Nous formatons dons la liste passée en argument pour obtenir ceci :
SELECT * FROM REGION WHERE idDpt IN ('75','76','89')
La seule difficulté est de formater dynamiquement la liste passée en argument.
Commençons notre script, nommé tst2.sh, par déclarer deux variables globales comme suit:
# déclarer une variable globale qui récupère la valeur de l'argument export argListeDpts="" # Et une autre pour la sortie formatée export listeDpts=" SELECT * FROM REGION WHERE idDpt IN ("
Pour cela, ajouter la première fonction nommée substrLastChar qui permet de substituer le dernier caractère par une parenthèse fermante par la suite:
substrlastChar() { phrase=$1 position=`expr ${#phrase} - 1 ` listeDpts=`expr substr $phrase 1 $position ` }
Puis la seconde fonction qui formate comme attendu la liste passée en argument:
splitterPhrase() { phrase=$1;OLDIFS=$IFS; IFS="\,"; for u in $phrase ; do listeDpts="$listeDpts'$u',"; done; IFS=$OLDIFS; substrLastChar listeDpts=$listeDpts")" }
Il reste à adapter la fonction lectureArgs afin de récupérer la valeur de l'argument dans la variable globale listeDpts.
lectureArgs() { while getopts "a:h" OPTION do case $OPTION in h) echo "help syntaxe="; exit 0;; a) argListeDpts=$OPTARG;; :) echo " option sans arg";exit 1;; \?) echo "option inconnue";exit 1;; esac done }
Enfin, le script proprement parlant contient ces lignes:
lectureArgs $@
splitterPhrase $argListeDpts
echo "resultat=$listeDpts"
L'exécution de ce script avec par exemple l'argument suivant:
./tst2.sh -a 75,76,79,99
renvoie à l'écran la sortie suivante :
resultat= SELECT * FROM REGION WHERE idDpt IN ('75','76','79','99')
Conclusion
Il y a certainement plusieurs façons d'arriver à ce ce résultat (utilisation de awk, sed,..), mais ce billet donne avec détails quelques éléments qui vous permettent d'être en mesure d'automatiser certaines tâches lors du déploiement d'applications sur des plateformes linux ou hp-ux. N'étant pas expert du script Shell, vos remarques sont les bienvenues. Enfin, il faut bien faire attention aux fameuses erreurs de manipulation des chaînes.