Les solutions du TP #2
Il n'y a rien de bien compliqué, il suffit d'être très rigoureux. Commençons par inclure le code d'une solution parmi l'ensemble des possibilités :
#!/bin/ksh FIN=0 # Selection de l'operation echo "Choisissez une operation :" echo " Creer une nouvelle archive 1" echo " Ajouter des fichiers dans une archive 2" echo " Lister le contenu d'une archive 3" echo " Extraire le contenu d'une archive 4" echo " Quitter le programme 0" while [ ${FIN} -eq 0 ] do read NUM_COMMANDE echo ${NUM_COMMANDE} FIN=1 case ${NUM_COMMANDE} in 1) COMMANDE="c";; 2) COMMANDE="r";; 3) COMMANDE="t";; 4) COMMANDE="x";; 0) exit;; *) echo "Commande non reconnue => recommencez !" FIN=0;; esac done # Selection des options FIN=0 echo "Choisissez une ou plusieurs options :" echo " Mode verbeux 1" echo " Respect des permissions 2" echo " Fin 0" while [ ${FIN} -eq 0 ] do echo "Options actuelles : " ${OPTIONS} read NUM_OPTION FIN=0 case ${NUM_OPTION} in 0) echo "Fin de selection des options : "${OPTIONS} FIN=1;; 1) OPTIONS="${OPTIONS}v";; 2) OPTIONS="${OPTIONS}p";; *) echo "Option non reconnue";; esac done # ne pas oublier d'ajouter le f de manipulation des fichiers OPTIONS=${OPTIONS}f # Selection du nom de l'archive et tests subsequents FIN=0 while [ ${FIN} -eq 0 ] do echo "Saisissez le nom de l'archive :" read NOM_ARCHIVE FIN=1 case ${NUM_COMMANDE} in 1) if [ -a "${NOM_ARCHIVE}" ] then echo "Avertissement : le fichier ${NOM_ARCHIVE} existe deja" echo "vous pouvez :" echo " L'ecraser 1" echo " Changer le nom du fichier 2" echo " Passer en mode ajout 3" echo " Abandonner l'operation 0" read NUM_COM2 case ${NUM_COM2} in 0) echo "Abandon des operations" exit;; 1) rm -f ${NOM_ARCHIVE};; 2) FIN=0;; 3) NUM_COMMANDE=2 COMMANDE="r";; esac fi;; 2 | 3 | 4) if [ -f "${NOM_ARCHIVE}" ] then FIN=1 else echo "Erreur : le fichier ${NOM_ARCHIVE} n'existe pas ou n'est pas un fichier normal" echo "vous pouvez :" echo " Changer le nom du fichier 1" echo " Abandonner l'operation 0" read NUM_COM2 if [ ${NUM_COM2} -eq 1 ] then FIN=0 else exit fi fi;; *) echo "cas par defaut : bizarre " exit;; esac done # Lecture du nom des fichiers echo "Choisissez le nom des fichiers" read SELECTION # Il ne reste plus qu'a executer la commande idoine ! tar ${COMMANDE}${OPTIONS} ${NOM_ARCHIVE} ${SELECTION}
Quelques commentaires :
Cet exercice est très simple, en effet, pour réussir les 2 premières questions, il suffit de travailler avec soin sur une variable compteur que l'on fait évoluer de 1 jusqu'au second argument.
#!/bin/ksh if (( ($# < 2) || ($# > 2) )) then echo "Nombre d'arguments incorrect " echo "Usage : ${0} nom_de_base nombre_de_replications" else NOMBRE_FINAL=${2} NOM_BASE=${1} COMPTEUR=1 while (( COMPTEUR <= NOMBRE_FINAL )) do echo "Ceci est le fichier numero ${COMPTEUR}" > ${NOM_BASE}.${COMPTEUR} (( COMPTEUR += 1 )) done fi
#!/bin/ksh if [ $# -lt 2 ] then echo "Nombre d'arguments incorrect " echo "Usage : ${0} nom_de_base nombre_de_replications" else NOMBRE_FINAL=${2} NOM_BASE=${1} COMPTEUR=1 while [ ${COMPTEUR} -le ${NOMBRE_FINAL} ] do echo "Ceci est le fichier numero ${COMPTEUR}" > ${NOM_BASE}.${COMPTEUR} COMPTEUR=`expr ${COMPTEUR} + 1` done fi
Cette solution est plus amusante. En effet, il nous faut construire par un programme externe la liste des n premiers entiers. Un tel programme n'est pas compliqué à écrire !
#include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[]) { int limite, compteur; if (argc != 2) { printf("Syntaxe non respectee : usage %s n\n",argv[0]); exit(1); } limite=atoi(argv[1]); for (compteur=1;compteur <= limite; compteur ++) printf("%d ",compteur); puts(""); return 0; }
Permettez moi de faire une remarque amusante. Dans les scripts shells, l'argument 0 n'est pas comptabilité dans $# alors qu'il est recensé dans argc pour les programmes C. Un bel exemple d'incohérence, non ?
Maintenant que nous disposons de ce programme (que nous appellerons compteur) il nous suffit de créer une boucle for dont le curseur prendra ses valeurs dans le retour de compteur :
#!/bin/ksh if (( $# != 2 )) then echo "Nombre d'arguments incorrect " echo "Usage : ${0} nom_de_base nombre_de_replications" else NOM_BASE=${1} PLAGE=`compteur ${2}` echo ${PLAGE} for COMPTEUR in ${PLAGE} do echo "Ceci est le fichier numero ${COMPTEUR}" > ${NOM_BASE}.${COMPTEUR} done fi
Et voila le travail ! Amusez vous à comparer les temps d'exécution avec la commande time et donnez m'en des nouvelles !
Nous allons procéder en plusieurs étapes en nous souvenant que :
La première chose à faire consiste à remplacer les paramètres positionnels par de vraies variables, par exemple :
REP_BASE=$1 EXT_INIT=$2 EXT_FIN=$3
Ceci présente au moins 2 avantages :
Dans un second temps, il faut rechercher la liste des fichiers avec find :
find ${REP_BASE} -name "*.${EXT_INIT}" -print
Il nous faut alors exécuter sed, ce qui ne pose pas de problème spécifique :
CTRL_A=`echo | tr '\012' '\001'`
sed -e "s${CTRL_A}^\(.*\)${EXT_INIT}${CTRL_A}& \1${EXT_FIN}${CTRL_A}"
Examinons néanmoins les lignes de code que nous avons tappées :
Finalement, il ne reste qu'à appliquer la commande mv sur le résultat de sed avec les paramètres suivants :
Le résultat final est le suivant :
#!/bin/ksh
REP_BASE=$1 EXT_INIT=$2 EXT_FIN=$3
CTRL_A=`echo | tr '\012' '\001'`
find ${REP_BASE} -name "*.${EXT_INIT}" -print \
| sed -e "s${CTRL_A}^\(.*\)${EXT_INIT}${CTRL_A}& \1${EXT_FIN}${CTRL_A}" \
| xargs -n2 mv
Il s'agit d'obtenir la liste de tous les utilisateurs lançant une certaine commande passée en premier argument. La commande ps est utilisée pour obtenir la liste de tous les processus en cours d'exécution, filtrée avec grep pour se limiter à la commande intéressante. Notons que nous n'utilisons pas directement grep sur le nom de la commande mais en prenant bien soin de créer un certain contexte autour du nom de celle-ci. Nous utilisons ensuite awk pour extraire la colonne contenant le nom de l'utilisateur. Afin d'obtenir une seule copie du nom de chaque utilisateur concerné, nous utilisons l'utilitaire standard uniq. Un petit coup d'oeil à man uniq nous apprend que cette commande ne travaille correctement que sur une liste triée, ce qui justifie l'appel intermédiaire à sort.
Le résultat est finalement :
#!/bin/ksh commande=$1 ps -elf | grep " ${commande}" | awk '{print $1}' | sort | uniq
Il s'agit tout simplement d'écrire un script sed contenant de multiples instructions de remplacement. Dans le cas du passage de code source vers HTML, il est impératif de traiter le caractère & en priorité. En effet, dans le cas contraire, comme vos précédents remplacements rajoutent ce caractère, un < serait d'abord remplacé par <, puis par &lt;!
Dans la transcription inverse, il faut traiter le & en dernier pour éviter qu'une construction HTML, certes rare mais valide, comme &lt; qui devra se traduire comme < (soit, en C, la prise d'adresse de la variable lt) ne se trouve en faite transcrite comme <.
Les deux scripts (eux même traités avec le premier d'entre eux !) sont :
# code2html.sed script de conversion source -> HTML /&/s/&/\&/g /</s/</\</g />/s/>/\>/g /"/s/"/\"/g
# html2code.sed script de conversion HTML -> source />/s/>/>/g /</s/</</g /"/s/"/"/g /&/s/&/"/g
Il faudra, bien entendu, encapsuler ces 2 scripts sed dans des scripts ksh pour les rendre plus agréables à utiliser.