UNIX STATION
La programmation "Shell"
Version 2.0
LA PROGRAMMATION "SHELL"
Edition novembre 2008
Frédéric Lang ([email protected])
1/89
UNIX STATION
La programmation "Shell"
Version 2.0
Licence de ce document
Permission est accordée de copier, distribuer et/ou modifier ce document selon les termes de la "Licence de Documentation Libre GNU" (GNU Free Documentation License), version 1.1 ou toute version ultérieure publiée par la Free Software Foundation. En particulier le verbe "modifier" autorise tout lecteur éventuel à apporter au document ses propres contributions ou à corriger d'éventuelles erreurs et lui permet d'ajouter son propre copyright dans la page "Registre des éditions" mais lui interdit d'enlever les copyrights déjà présents et lui interdit de modifier les termes de cette licence. Ce document ne peut être cédé, déposé ou distribué d'une autre manière que l'autorise la "Licence de Documentation Libre GNU" et type annule automatiquement les droits d'utiliser ce document sous cette licence. Toutefois, des tiers ayant reçu des copies de ce document ont le droit d'utiliser ces copies et continueront à bénéficier de ce droit tant qu'ils respecteront pleinement les conditions de la licence.
tentative de ce
toute
La version actuelle de ce document est la 2.0 et sa version la plus récente est disponible en téléchargement à l'adresse http://fr.lang.free.fr
Copyright © 2007 Frédéric Lang ([email protected])
Edition novembre 2008
Frédéric Lang ([email protected])
2/89
UNIX STATION
La programmation "Shell"
Version 2.0
Registre des éditions
Version 1.0
Date
30 juillet 2004
Description des modifications
Mise en place du registre des éditions Corrections mineures (syntaxe, etc)
Auteur des modifications
© Frédéric Lang ([email protected])
1.1
1.2
26 août 2004
Relecture – Corrections mineures
© Frédéric Lang ([email protected])
24 novembre 2004 Rajout du test de la numéricité d'une variable en "réel"
© Frédéric Lang ([email protected])
Vérification et corrections majeures de tous les exercices
1.3
24 février 2005
Rectification sur le paragraphe des fonctions Corrections mineures
© Frédéric Lang ([email protected])
1.4
15 septembre 2005 Rajout de la variable "REPLY" dans le "select" et dans la
© Frédéric Lang ([email protected])
© Frédéric Lang ([email protected])
2.0
26 juin 2007
liste des variables internes Corrections mineures
Rajout d'un paragraphe dans l'introduction Prise en compte de nouveaux shells Réécriture complète du chapitre des fonctions Correction sur les substitutions de variables Rajout de la variable "REPLY" dans le "read" Correction sur la commande "test" Création du chapitre sur les outils avancés Révision de l'instruction "set" Rajout de l'instruction "source" Rajout de l'instruction "trap" Rajout de l'instruction "let" Rajout des instructions "typeset" et "declare" Rajout des instructions "locale"" Révision de l'instruction "getopts" Correction sur la commande "expr" Correction sur la commande "exec" Rajout de la commande "seq" Rajout de la commande "xargs" Rajout de la commande "getopt" Révision majeure des exemples "division" et "résolution polynômes" Rajout de l'exemple "tours de Hanoï" Remplacement de l’adresse email "[email protected]" par "[email protected]"
Edition novembre 2008
Frédéric Lang ([email protected])
3/89
UNIX STATION
La programmation "Shell"
Version 2.0
SOMMAIRE
I)
INTRODUCTION_________________________________________________________________________ 7 1) POURQUOI PROGRAMMER EN SHELL ? _________________________________________________________ 8 2) PRESENTATION __________________________________________________________________________ 8 3) IMPERATIFS ____________________________________________________________________________ 10 4) CONVENTIONS DU SUPPORT DE COURS _______________________________________________________ 10
II) ELEMENTS DE BASE DU LANGAGE______________________________________________________ 11 1) L'AFFICHAGE___________________________________________________________________________ 11 2) LES COMMENTAIRES _____________________________________________________________________ 11 3) LE DEBOGUEUR _________________________________________________________________________ 11 4) QUI EXECUTE ? _________________________________________________________________________ 12
a) b) c)
III) LES VARIABLES________________________________________________________________________ 13 1) L'AFFECTATION – L'ACCES ________________________________________________________________ 13 Les variables simples__________________________________________________________________ 13 Les tableaux (shells évolués) ____________________________________________________________ 14 Remarque___________________________________________________________________________ 14 2) LA SUBSTITUTION _______________________________________________________________________ 15 a) Tous types de Shell ___________________________________________________________________ 15 b) Uniquement en Korn Shell et Bourne Again Shell (et shells descendants) _________________________ 16 c) Uniquement en Bourne Again Shell (et shells descendants) ____________________________________ 16 Remarque___________________________________________________________________________ 16 d) 3) LA SAISIE EN INTERACTIF _________________________________________________________________ 17 4) LA PROTECTION ________________________________________________________________________ 17 5) LA SUPPRESSION ________________________________________________________________________ 18 6) LA VISIBILITE __________________________________________________________________________ 18 7) LE TYPAGE ("KORN SHELL" ET "BOURNE AGAIN SHELL" ET SHELLS DESCENDANTS) ___________________ 20 8) LES VARIABLES PREDEFINIES ______________________________________________________________ 21
Publicité
IV) LA "SOUS-EXECUTION" ________________________________________________________________ 22
V) LES PARAMETRES _____________________________________________________________________ 24 1) RECUPERATION DES PARAMETRES___________________________________________________________ 24 2) DECALAGE DES PARAMETRES ______________________________________________________________ 25 3) RE AFFECTATION VOLONTAIRE DES PARAMETRES_______________________________________________ 26 4) LE SEPARATEUR DE CHAMPS INTERNES _______________________________________________________ 26
VI) NEUTRALISATION DES META CARACTERES ____________________________________________ 27 1) RAPPEL SUR LES META CARACTERES_________________________________________________________ 27 2) LE "BACKSLASHE"_______________________________________________________________________ 28 3) L'APOSTROPHE OU "QUOTTE SIMPLE" ________________________________________________________ 28 4) LE DOUBLE GUILLEMET___________________________________________________________________ 28
VII) LES CONTROLES BOOLEENS ___________________________________________________________ 29 1) INTRODUCTION _________________________________________________________________________ 29 2) LA COMMANDE "TEST" ___________________________________________________________________ 30 a) Test simple sur les fichiers______________________________________________________________ 30 b) D'autres test simple sur les fichiers ("Korn Shell" et "Bourne Again Shell" et shells descendants) ______ 30 Test complexe sur les fichiers ("Korn Shell" et en "Bourne Again Shell" et shells descendants) ________ 31 c) Test sur les longueurs de chaînes de caractères _____________________________________________ 31 d) Test sur les chaînes de caractères ________________________________________________________ 31 e) f) Test sur les numériques ________________________________________________________________ 32 g) Connecteurs d'expression ______________________________________________________________ 32 3) LES COMMANDES "TRUE" ET "FALSE" ________________________________________________________ 33 4) LA COMMANDE "READ" ___________________________________________________________________ 33
VIII) LES STRUCTURES DE CONTROLES ______________________________________________________ 34 INTRODUCTION _________________________________________________________________________ 34
1)
Edition novembre 2008
Frédéric Lang ([email protected])
4/89
UNIX STATION
La programmation "Shell"
Version 2.0
2) L'ALTERNATIVE SIMPLE __________________________________________________________________ 34 3) L'ALTERNATIVE COMPLEXE________________________________________________________________ 35 4) LE BRANCHEMENT A CHOIX MULTIPLE _______________________________________________________ 36 5) LA BOUCLE SUR CONDITION _______________________________________________________________ 37 6) LA BOUCLE SUR LISTE DE VALEURS__________________________________________________________ 38 INTERRUPTION D'UNE OU PLUSIEURS BOUCLES _________________________________________________ 39 7) INTERRUPTION D'UN PROGRAMME___________________________________________________________ 40 8) 9) LE GENERATEUR DE MENUS EN BOUCLE (KORN SHELL ET BOURNE AGAIN SHELL ET SHELLS DESCENDANTS)_ 40
IX) LES FONCTIONS _______________________________________________________________________ 41 INTRODUCTION _________________________________________________________________________ 41 1) 2) PASSAGE DE VALEURS____________________________________________________________________ 42 3) RETOUR DE FONCTION____________________________________________________________________ 43 4) RENVOI D'UNE VALEUR PAR UNE FONCTION ___________________________________________________ 44 5) PORTEE DES VARIABLES __________________________________________________________________ 45 IMBRICATION DE FONCTIONS_______________________________________________________________ 46 6) 7) LA TRACE DE L'APPELANT _________________________________________________________________ 48
X) LES INSTRUCTIONS AVANCEES _________________________________________________________ 49 1) L'INCLUSION DE SCRIPT DANS UN SCRIPT______________________________________________________ 49 2) LA PROTECTION CONTRE LES SIGNAUX _______________________________________________________ 50 3) TRANSFORMER UNE EXPRESSION EN ORDRE "SHELL" ____________________________________________ 51 4) ARITHMETIQUE SUR LES VARIABLES ("KORN SHELL" ET "BOURNE AGAIN SHELL" ET SHELLS DESCENDANTS) 51 5) CREER DE NOUVEAUX CANAUX D'ENTREES/SORTIES _____________________________________________ 52 6) GERER LES OPTIONS _____________________________________________________________________ 53
XI) LES COMPLEMENTS____________________________________________________________________ 55 1) EVALUER DES EXPRESSIONS REGULIERES AVEC LA COMMANDE "EXPR" ______________________________ 55 Arithmétique ________________________________________________________________________ 55 a) b) Comparaison ________________________________________________________________________ 56 Travail sur chaînes de caractères ________________________________________________________ 56 c) 2) RECHERCHER DES CHAINES AVEC LA COMMANDE "GREP"_________________________________________ 57 3) DECOUPER DES LIGNES AVEC LA COMMANDE "CUT" _____________________________________________ 58 4) TRIER LES INFORMATIONS AVEC LA COMMANDE "SORT"__________________________________________ 58 5) FILTRER LES INFORMATIONS AVEC LA COMMANDE "SED" _________________________________________ 59 6) TRANSFORMER LES INFORMATIONS AVEC LA COMMANDE "TR" ____________________________________ 59 7) COMPTER LES OCTETS AVEC LA COMMANDE "WC" ______________________________________________ 60 8) AFFICHER UNE SEQUENCE DE NOMBRES AVEC LA COMMANDE "SEQ" ________________________________ 60 9) AFFICHER DES DONNEES FORMATEES AVEC LA COMMANDE "PRINTF"________________________________ 60 10) DECOUPER LES NOMS AVEC LES COMMANDES "BASENAME" ET "DIRNAME" ___________________________ 61 11) FILTRER LES ARGUMENTS AVEC LA COMMANDE "XARGS"_________________________________________ 61 12) MATHEMATIQUES EN VIRGULE FLOTTANTE AVEC LA COMMANDE "BC" ______________________________ 62 13) GERER LES OPTIONS AVEC LA COMMANDE "GETOPT" ____________________________________________ 62 14) GERER SON AFFICHAGE A L'ECRAN AVEC LES CODES "ESCAPE" ____________________________________ 64
XII) EXEMPLES DIVERS_____________________________________________________________________ 66 1) AFFICHER UNE PHRASE SANS QUE LE CURSEUR PASSE A LA LIGNE SUIVANTE __________________________ 66 2) VERIFIER L'EXISTENCE D'UN FICHIER QUEL QUE SOIT SON TYPE ____________________________________ 66 3) VERIFIER LA NUMERICITE D'UNE VARIABLE EN TERME DE "NOMBRE ENTIER" __________________________ 66 4) VERIFIER LA NUMERICITE D'UNE VARIABLE EN TERME DE "NOMBRE REEL" ___________________________ 67 5) NOM DE BASE DU REPERTOIRE COURANT _____________________________________________________ 67 6) VERIFICATION DE L'AUTORISATION D'ACCES D'UN UTILISATEUR QUELCONQUE_________________________ 68 7) MEMBRES D'UN GROUPE __________________________________________________________________ 69 8) SERVEURS GERES PAR "INETD" _____________________________________________________________ 70 9) RECHERCHE D'UNE COMMANDE ____________________________________________________________ 71 10) ARBORESCENCE D'UN REPERTOIRE __________________________________________________________ 72 11) FACTORIELLE D'UN NOMBRE _______________________________________________________________ 74 12) PGCD DE DEUX NOMBRES ________________________________________________________________ 76 13) DIVISION EN NOMBRES REELS ______________________________________________________________ 78 2 14) RESOLUTION DE POLYNOME DU SECOND DEGRE : AX + BX + C = 0 ________________________________ 83 15) TOURS DE HANOÏ _______________________________________________________________________ 86
Edition novembre 2008
Frédéric Lang ([email protected])
5/89
UNIX STATION
La programmation "Shell"
Version 2.0
INDEX ______________________________________________________________________________________ 88
Edition novembre 2008
Frédéric Lang ([email protected])
6/89
UNIX STATION
La programmation "Shell"
Version 2.0
I)
INTRODUCTION
Le Shell est un "INTERPRETEUR DE COMMANDE". Il ne fait pas partie du système d'exploitation UNIX; et c'est la raison pour laquelle il porte ce nom "coquille", qui indique son état détaché du "noyau" Unix. Son rôle est d'analyser la commande tapée afin de faire réagir le système pour qu'il réponde aux besoins de l'utilisateur. C'est le premier langage de commandes développé sur Unix par Steve Bourne. Une comparaison rapide pourrait l'apparenter au DOS (Disc Operating System) développé par Microsoft, mais cette comparaison n'est là que pour illustrer le rôle du Shell par rapport à Unix.
De par sa qualité de "programme externe", il n'est pas unique. En effet, rien n'empêche n'importe quel programmeur de programmer une boucle qui attend une chaîne au clavier, analyse cette chaîne et appelle ensuite le système pour exécuter l'ordre demandé. C'est la raison pour laquelle il existe plusieurs shells. Nous trouvons entre autres (liste non-exhaustive) : (cid:1) le Bourne Shell ("/bin/sh") (cid:1) le Korn Shell ("/bin/ksh") (cid:1) le c Shell ("/bin/csh") pour les utilisateurs préférant un langage apparenté au "C" (cid:1) le Job Shell ("/bin/jsh") (cid:1) le Shell réseau ("/bin/rsh") (cid:1) le Bourne Again Shell ("/bin/bash") qui a repris le Bourne Shell mais qui l'a agrémenté de nouvelles fonctionnalités (rappel de commandes, complétion automatique, etc.) (cid:1) le c Shell amélioré ("/bin/tcsh") améliorant le c Shell tout en lui restant compatible (cid:1) l'Almquist Shell ("/bin/ash") améliorant le Bourne Shell tout en étant plus compact que le Bourne Again Shell (cid:1) le z Shell ("/bin/zsh") (cid:1) et d'autres encore à venir…
C'est un langage de commandes mais aussi un langage de programmation. Il permet donc : (cid:1) l'utilisation de variables (cid:1) la mise en séquence de commandes (cid:1) l'exécution conditionnelle de commandes (cid:1) la répétition de commandes
Un programme shell appelé aussi "script" est un outil facile à utiliser pour construire des applications en regroupant des appels systèmes, outils, utilitaires et programmes compilés. Concrètement, le répertoire entier des commandes Unix, des utilitaires et des outils est disponible à partir d'un script shell. Les scripts shell conviennent parfaitement pour des tâches d'administration du système et pour d'autres routines répétitives ne réclamant pas les particularités d'un langage de programmation structuré.
Edition novembre 2008
Frédéric Lang ([email protected])
7/89
UNIX STATION
La programmation "Shell"
Version 2.0
1) Pourquoi programmer en shell ?
Aucun langage de programmation n'est parfait. Il n'existe même pas un langage meilleur que d'autres ; il n'y a que des langages en adéquation ou peu conseillés pour des buts particuliers. (Herbert Mayer).
Une connaissance fonctionnelle de la programmation shell est essentielle à quiconque souhaite devenir efficace en administration système car toute l'administration dans Unix est écrite en shell. Une compréhension détaillée des scripts d'administration est importante pour analyser le comportement du système, voire le modifier. De plus, la seule façon pour vraiment apprendre la programmation des scripts est d'écrire des scritpts.
Quand ne pas programmer en shell ? (cid:1) Pour des tâches demandant beaucoup de ressources ou beaucoup de rapidité (cid:1) Pour une application complexe où une programmation structurée est nécessaire (typage des variables, prototypage de fonctions, tableaux multi dimensionels, listes chaînées, arbres, etc.) (cid:1) Pour des situations où la sécurité est importante (protection contre l'intrusion, le vandalisme) (cid:1) Pour des applications qui accèdent directement au matériel (cid:1) Pour des applications qui devront générer ou utiliser une interface graphique utilisateur (G.U.I.) (cid:1) Pour des applications propriétaires (un script est forcément lisible par celui qui l'utilise)
Pour toutes ces situations, Unix offre une gamme de langages de scripts plus puissants comme le Perl, Tcl, Python, Ruby ; voire des langages compilés de haut niveau comme le C et le C++.
2) Présentation
Il existe deux moyens de "programmer" en Shell. Le premier, est dit en "direct". L'utilisateur tape "directement" la ou les commandes qu'il veut lancer. Si cette commande a une syntaxe qui l'oblige à être découpée en plusieurs lignes, le Shell indiquera par l'affichage d'un "prompt secondaire" que la commande attend une suite et n'exécutera réellement la commande qu'à la fin de la dernière ligne.
Exemple :
Prompt> date Tue Jan 16 17:26:50 NFT 2001 Prompt> pwd /tmp Prompt > if test 5 = 5 Prompt secondaire> then Prompt secondaire> echo vrai Prompt secondaire> fi vrai
Edition novembre 2008
Frédéric Lang ([email protected])
8/89
UNIX STATION
La programmation "Shell"
Version 2.0
Le second, est dit en "script" ; appelé aussi "batch" ou "source Shell". L'utilisateur crée un fichier texte par l'éditeur de son choix (ex : "vi"). Il met dans ce script toutes les commandes qu'il voudra lui faire exécuter ; en respectant la règle de base de ne mettre qu'une seule commande par ligne. Une fois ce script fini et sauvegardé, il le rend exécutable par l'adjonction du droit "x" (cf. Gestion des fichiers). Il peut ensuite lancer l'exécution de ce fichier comme n'importe quelle autre commande Unix (attention donc au contenu de la variable "PATH" qui indique où aller chercher une commande lorsqu'on la lance sans préciser où elle se trouve). Toutes les commandes inscrites dans le fichier texte seront exécutées séquentiellement.
Exemple :
Contenu du fichier "prog" :
date pwd if test 5 = 5 then
echo "vrai"
Publicité
fi
Lancement de l'éditeur Prompt> vi prog
Mise à jour du droit d'exécution Prompt> chmod a+x prog
Exécution du script pris dans le répertoire courant Prompt> ./prog Tue Jan 16 17:26:50 NFT 2001 /tmp oui
Remarque : L'adjonction du droit "x" n'est pas obligatoire, mais l'utilisateur devra alors demander spécifiquement à un Shell quelconque d'interpréter le "script".
Exemple : L'utilisateur demande d'interpréter le script par l'intermédiaire du "Bourne Shell"
Exemple : L'utilisateur demande d'interpréter le script par l'intermédiaire du "Korn Shell"
Prompt> sh prog Tue Jan 16 17:26:50 NFT 2001 /tmp oui
Prompt> ksh prog Tue Jan 16 17:26:50 NFT 2001 /tmp oui
Edition novembre 2008
Frédéric Lang ([email protected])
9/89
UNIX STATION
La programmation "Shell"
Version 2.0
3) Impératifs
Comme il l'a été dit, le Shell est un "interpréteur". C'est à dire que chaque ligne est analysée, vérifiée et exécutée. Afin de ne pas trop limiter la rapidité d'exécution, il y a très peu de règles d'analyse. Cela implique un grande rigidité d'écriture de la part du programmeur. Une majuscule n'est pas une minuscule ; et surtout, deux éléments distincts sont toujours séparés par un espace… à une exception près qui sera vue plus tard.
Enfin, le premier mot de chaque ligne, si la ligne n'est pas mise en commentaire, doit être une instruction Shell "correcte". On appelle "instruction" soit (cid:1) l'appel d'une commande "Unix" (ex : date) (cid:1) l'appel d'un autre script "Shell" (ex : ./prog) (cid:1) une commande interne du langage (ex : cd…)
Exemple :
Prompt> echoBonjour sh: echoBonjour: not found Prompt> echo Bonjour Bonjour
4) Conventions du support de cours
Il est difficile d'écrire un support de cours en essayant de faire ressortir des points importants par l'utilisation de caractères spécifiques (guillemets, parenthèses, etc.) sur un langage utilisant certains caractères comme instructions spécifiques (guillemets, parenthèses, etc.). De plus, le lecteur ne sait pas forcément distinguer les éléments provenant de l'ordinateur des éléments qu'il doit taper au clavier. C'est pourquoi, il est nécessaire de définir des conventions (cid:1) La chaîne "Prompt>" ou "Prompt2>" présente dans les exemples de ce cours est une "invite" ; appelée aussi "prompt". C'est une chaîne affichée par l'interpréteur dans lequel travaille l'utilisateur afin de lui indiquer qu'il attend une instruction. Cette chaîne n'est pas forcément la même pour des utilisateurs différents. Dans ce support, sa présence signifie que l'exemple proposé peut être tapé directement en ligne, sans obligatoirement passer par un fichier script. (cid:1) La chaîne "#!/bin/sh" présente dans les exemples de ce cours est expliquée plus tard. Dans ce support, sa présence signifie qu'il vaut mieux écrire l'exemple proposé dans un fichier "script" afin de pouvoir exécuter l'exemple plusieurs fois pour mieux analyser son fonctionnement. (cid:1) Les syntaxes présentes en début de paragraphe donnent la syntaxe exacte d'une commande. Elles sont donc présentées sans prompt ni ligne "#!/bin/sh". (cid:1) Des éléments mis entre crochets "[elem]" signifient qu'ils sont facultatifs. L'utilisateur peut les utiliser ou pas, mais ne doit en aucun cas mettre de crochets dans sa frappe ou son programme. (cid:1) Le caractère n employé dans la syntaxe signifie "nombre entier quelconque positif ou, parfois, nul". (cid:1) Le caractère "|" employé dans la syntaxe signifie "choix entre l'élément situé à gauche ou à droite du |". (cid:1) Les points de suspension "…" signifient que l'élément placé juste avant eux peut être répété autant de fois que l'on désire.
Edition novembre 2008
Frédéric Lang ([email protected])
10/89
UNIX STATION
La programmation "Shell"
Version 2.0
II) ELEMENTS DE BASE DU LANGAGE
1) L'affichage
L'affichage est la première commande qu'un programmeur débutant pourra être tenté de faire. Cela lui permet en effet de visualiser directement à l'écran le résultat de ses actions. L'affichage en Shell se fait avec la commande "echo". Exemple :
Prompt> echo Hello World
2) Les commentaires
Un commentaire sert à améliorer la lisibilité du script. Il est placé en le faisant précéder du caractère dièse ("#"). Tout ce qui suit ce dièse est ignoré jusqu'à la fin de la ligne ; ce qui permet de mettre un commentaire sur une ligne d'instructions. Il ne faut pas oublier alors l'espace séparant la fin de l'instruction et le début du commentaire. Exemple :
#!/bin/sh # Ce programme affiche la date date
Cette ligne est la ligne qui affiche la date
3) Le débogueur
Une procédure longue et difficile peut ne pas réussir du premier coup. Afin de détecter l'erreur, le Shell offre un outil de débogage. Il s'agit de l'instruction "set" agrémentée d'une ou plusieurs options suivantes : (cid:1) v : affichage de chaque instruction avant analyse => il affiche le nom des variables (cid:1) x : affichage de chaque instruction après analyse => il affiche le contenu des variables (cid:1) e : sortie immédiate sur erreur
Chaque instruction "set -…" active l'outil demandé qui sera désactivé par l'instruction "set +…". On peut ainsi activer le "traqueur" sur une portion précise du programme source.
Exemple :
#!/bin/sh set –x date set +x
Activation du débogage à partir de maintenant # Cette ligne est la ligne qui affiche la date # Désactivation du débogage à partir de maintenant
Remarque : Compte tenu du flot important d'informations produit par ces outils, il peut être avantageux de lui préférer un affichage des variables pouvant causer l'erreur (commande "echo").
Edition novembre 2008
Frédéric Lang ([email protected])
11/89
UNIX STATION
La programmation "Shell"
Version 2.0
4) Qui exécute ?
Rappelons qu'il existe plusieurs shells et que chacun d'eux possède des caractéristiques différentes. De plus, chaque utilisateur Unix peut demander à travailler dans le Shell de sa convenance. Il s'ensuit qu'un script écrit par un utilisateur travaillant en Bourne Shell ne fonctionnera pas forcément s'il est exécuté par un utilisateur travaillant en C-Shell.
L'utilisateur peut visualiser le Shell dans lequel il travaille en tapant la commande suivante:
Prompt> echo $0
Cependant, Unix cherche à assurer la portabilité de ses programmes. Il est donc nécessaire qu'un script écrit par un utilisateur travaillant en Bourne Shell puisse être exécuté par tous les utilisateurs, quels que soient leurs shells de travail. Pour cela, il convient d'indiquer dans le script quel interpréteur utiliser pour exécuter ledit script. Si cette indication n'existe pas, le système utilisera l'interpréteur de travail affecté à l'utilisateur pour analyser et exécuter le script en question, interpréteur pas forcément compatible avec la syntaxe du script. Cette indication se porte en début de script avec la ligne "#!interpréteur".
Exemple en Bourne Shell :
#!/bin/sh date
Ce script sera traité par le programme "/bin/sh" (Bourne Shell) # Demande à l'interpréteur "/bin/sh" de lancer le programme "date"
Exemple en Korn Shell :
#!/bin/ksh date
Ce script sera traité par le programme "/bin/ksh" (Korn Shell) # Demande à l'interpréteur "/bin/ksh" de lancer le programme "date"
Ici, cas particulier, le caractère "#" (dièse) de la première ligne combiné au caractère "!" (point d'exclamation) n'est plus pris comme un commentaire mais comme une instruction indiquant quel programme a la charge d'analyser le script.
Remarque: Ce cours proposera globalement une syntaxe Bourne Shell avec quelques éléments spécifiques aux shells de même famille dits "plus évolués" (Korn Shell ou Bourne Again Shell) qui seront indiqués au moment où cela sera nécessaire. Le Bourne Shell étant intégralement supporté par le Korn Shell et le Bourne Again Shell (et leurs descendants) ; cela permet une compatibilité ascendante (un script en Bourne Shell fonctionnera toujours en environnements Korn Shell ou Bourne Again Shell ou shells descendants).
Publicité
Autre exemple (ne fonctionne qu'une seule fois) :
#!/bin/rm # Le script s'efface donc lui-même - Ici le script est déjà effacé # Quoi que l'on mette ici, cela ne sera pas exécuté, cela n'existe déjà plus…
Ce script sera traité par le programme "/bin/rm" (effacement)
Edition novembre 2008
Frédéric Lang ([email protected])
12/89
UNIX STATION
La programmation "Shell"
Version 2.0
III) LES VARIABLES
Il n'est pas de langage sans variable. Une variable sert à mémoriser une information afin de la réutiliser ultérieurement. Elles sont créées par le programmeur au moment où il en a besoin. Il n'a pas besoin de les déclarer d'un type particulier et peut en créer quand il veut, où il veut. Leur nom est représenté par une suite de caractères commençant impérativement par une lettre ou le caractère _ (souligné ou underscore) et comportant ensuite des lettres, des chiffres ou le caractère souligné. Il ne doit pas correspondre à un des mots clefs du Shell. Leur contenu est interprété exclusivement comme du texte. Il n'existe donc pas, en Bourne Shell, d'instruction d'opération sur des variables ou sur du nombre (addition, soustraction, etc.). Il n'est pas non plus possible d'avoir des variables dimensionnées (tableaux). Mais cela est possible en Korn Shell et Bourne Again Shell (et shells descendants).
Il est important de noter que le Shell reconnaît, pour toute variable, deux états : (cid:1) non définie (non-existence) : elle n'existe pas dans la mémoire (cid:1) définie (existence) : elle existe dans la mémoire ; même si elle est vide
1) L'affectation – L'accès
a) Les variables simples
Syntaxe :
variable=chaîne
L'affectation d'une variable simple (il n'y a pas de possibilité de créer de tableau en Bourne Shell ) se fait par la syntaxe "variable=chaîne".
C'est la seule syntaxe du Shell qui ne veuille pas d'espace dans sa structure sous peine d'avoir une erreur lors de l'exécution.
Dans le cas où on voudrait entrer une chaîne avec des espaces dans la variable, il faut alors encadrer la chaîne par des guillemets simples ou doubles (la différence entre les deux sera vue plus tard). A partir du moment où elle a été affectée, une variable se met à exister dans la mémoire, même si elle a été affectée avec "rien". L'accès au contenu de la variable s'obtient en faisant précéder le nom de la variable du caractère "$". Exemples :
Prompt> nom="Pierre" Prompt> objet="voiture" Prompt> coul=bleue Prompt> echo "Il se nomme $nom" Prompt> txt="$nom a une $objet $coul" # Mélange de variables et texte dans une variable Prompt> echo txt Prompt>echo $txt
Affectation de "Pierre" dans la variable "nom" # Affectation de "voiture" dans la variable "objet" # Affectation de"bleu" dans la variable "coul" # Affichage d'un texte et d'une variable
Attention à ne pas oublier le caractère "$" # Affichage de la variable "txt"
Edition novembre 2008
Frédéric Lang ([email protected])
13/89
UNIX STATION
La programmation "Shell"
Version 2.0
b) Les tableaux (shells évolués)
Syntaxe :
variable[n]=chaîne
variable=(chaîne1 chaîne2 …)
Le Korn Shell, Bourne Again Shell et shells descendants) permettent de créer des tableaux à une seule dimension. L'affectation d'un élément d'un tableau se fait par la syntaxe "variable[n]=chaîne". Dans ce cas précis, les crochets ne signifient pas "élément facultatif" mais bien "crochets" et le programmeur doit les mettre dans sa syntaxe. L'indice "n" que l'on spécifie entre les crochets doit être impérativement positif ou nul; mais il n'a pas de limite maximale. De plus, rien n'oblige le programmeur à remplir le nème élément avant d'aller remplir le (n + 1)ème. Il est possible de remplir en une seule instruction les "n" premiers éléments du tableau en utilisant la syntaxe "variable=(chaîne1 chaîne2 …)". Dans cette syntaxe où l'utilisation de parenthèses "( )" est obligatoire, le texte "chaîne1" ira dans la variable "variable[0]"; le texte "chaîne2" ira dans la variable "variable[1]"; etc. Cette syntaxe remplace tout le tableau par les seules chaînes situées entre parenthèses. L'ancien contenu éventuel disparaît alors pour être remplacé par le nouveau.
L'accès au contenu de la variable d'indice "n" s'obtient en encadrant le nom de la variable indicée par des accolades "{ }" et en faisant précéder le tout du caractère "$". Si on remplace la valeur de l'indice par le caractère "*"; le Shell concatènera tous les éléments du tableau en une chaîne unique et renverra cette dernière. Et si on remplace la valeur de l'indice par le caractère "@"; le Shell transformera chaque élément du tableau en chaîne et renverra ensuite l'ensemble de toutes ces chaînes concaténées. Visuellement; il n'y a aucune différence dans le résultat entre l'utilisation des caractères "*" ou "@".
Dans des environnements de shells acceptant automatiquement transformée en tableau à un seul élément d'indice "[0]".
tableaux,
les
toute variable simple est
Exemple :
Prompt> nom[1]="Pierre" Prompt> nom[5]="Paul" Prompt> nom="Jacques" Prompt> i=5 Prompt>prenom=(Pim Pam Poum) Prompt> echo "Voici mes 3 noms: ${nom[0]}, ${nom[1]} et ${nom[$i]}" Prompt> echo "Mon tableau de noms contient ${nom[*]}" Prompt> echo "Mon tableau de prénoms contient ${prenom[@]}"
Affectation de "Pierre" dans la variable "nom[1]" # Affectation de "Paul" dans la variable "nom[5]" # Affectation de "Jacques" dans la variable "nom[0]" # Affectation de "5" à la variable "i" (ou "i[0]") # Affectation de 3 prénoms dans un tableau
c) Remarque
Même si cela est possible de façon limitée (cf. commande eval), il est difficile et déconseillé de vouloir manipuler des "variables de variable" (connues dans d'autres langages sous le nom "pointeurs"). Autrement dit, la syntaxe "$$var" qui pourrait vouloir dire "contenu du contenu de la variable var" signifie en réalité "contenu de la variable $$" (sera vue ultérieurement) suivi de la chaîne "var".
Edition novembre 2008
Frédéric Lang ([email protected])
14/89
UNIX STATION
La programmation "Shell"
Version 2.0
2) La substitution
On peut utiliser des séquenceurs spéciaux pour modifier la manière dont le Shell va renvoyer le contenu de ou des variables demandées.
a) Tous types de Shell
(cid:1) ${var} : renvoie le contenu de "$var". Il sert à isoler le nom de la variable par rapport au contexte de son utilisation. Ceci évite les confusions entre ce que l'utilisateur désire "${prix}F" (variable "prix" suivi du caractère "F") et ce que le Shell comprendrait si on écrivait simplement "$prixF" (variable "prixF"). (cid:1) ${var-texte} : renvoie le contenu de la variable "var" si celle-ci est définie (existe en mémoire) ; sinon renvoie le texte "texte". (cid:1) ${var:-texte} : renvoie le contenu de la variable "var" si celle-ci est définie et non vide ; sinon renvoie le texte "texte". (cid:1) ${var+texte} : renvoie le texte "texte" si la variable "var" est définie ; sinon ne renvoie rien (cid:1) ${var:+texte} : renvoie le texte "texte" si la variable "var" est définie et non-vide ; sinon ne renvoie rien (cid:1) ${var?texte} : renvoie le contenu de la variable "var" si celle-ci est définie ; sinon affiche le texte "texte" comme message d'erreur (implique donc l'arrêt du script). (cid:1) ${var:?texte} : renvoie le contenu de la variable "var" si celle-ci est définie et non-vide ; sinon affiche le texte "texte" (comme "${var:-texte}") comme message d'erreur (implique donc l'arrêt du script). (cid:1) ${var=texte} : renvoie le contenu de la variable "var" si celle-ci est définie, sinon affecte le texte "texte" à la variable "var" avant de renvoyer son contenu. (cid:1) ${var:=texte} : renvoie le contenu de la variable "var" si celle-ci est définie et non-vide, sinon affecte le texte "texte" à la variable "var" avant de renvoyer son contenu.
Edition novembre 2008
Frédéric Lang ([email protected])
15/89
UNIX STATION
La programmation "Shell"
Version 2.0
b) Uniquement en Korn Shell et Bourne Again Shell (et shells descendants)
(cid:1) ${var[n]} : renvoie le contenu du nième élément du tableau "var". (cid:1) ${var[*]} : concatène tous les éléments présents dans le tableau "var" en une chaîne unique et renvoie cette dernière. (cid:1) ${var[@]} : transforme individuellement chaque élément présent dans le tableau "var" en une chaîne et renvoie la concaténation de toutes les chaînes. (cid:1) ${var#texte} : Si "texte" contient un méta caractère, alors il sera étendu jusqu'à la plus petite correspondance avec le contenu de "var" pris à partir du début. Si cette correspondance est trouvée, elle est alors supprimée du début de "var". (cid:1) ${var##texte} : Si "texte" contient un méta caractère, alors il sera étendu jusqu'à sa plus grande correspondance avec le contenu de "var" pris à partir du début. Si cette correspondance est trouvée, elle est alors supprimée du début de "var". (cid:1) ${var%texte} : Si "texte" contient un méta caractère, alors il sera étendu jusqu'à sa plus petite correspondance avec le contenu de "var" pris à partir de la fin. Si cette correspondance est trouvée, elle est alors supprimée de la fin de "var". (cid:1) ${var%%texte} : Si "texte" contient un méta caractère, alors il sera étendu jusqu'à sa plus grande correspondance avec le contenu de "var" pris à partir de la fin. Si cette correspondance est trouvée, elle est alors supprimée de la fin de "var". (cid:1) ${#var} : renvoie le nombre de caractères contenus dans la variable "var". Si la variable est un tableau, renvoie alors le nombre d'éléments du tableau. (cid:1) $((expression)) : renvoie la valeur numérique de l'expression demandée.
c) Uniquement en Bourne Again Shell (et shells descendants)
Publicité
(cid:1) ${!var} : utilise le contenu de la variable "var" comme un nom de variable et renvoie le contenu de cette dernière (permet donc de simuler un pointeur). (cid:1) ${var:x:y} : renvoie les "y" caractères de la variable "var" à partir du caractère n° "x" (attention; le premier caractère d'une variable por