Script Shell : Formater des chaînes à l’intérieur des scripts

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.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.