Aide-mémoire Unix : Outils de développement


Table des matières de chapitre

  1. Expressions régulières
  2. Éditeur vi
  3. tr
  4. sed
  5. awk
  6. perl
  7. Compilateurs
  8. make
  9. Debugger
  10. Outils Workshop (SPARCworks/ProWorks)


1. Expressions régulières

Une "expression régulière" (global regular expression) est une suite de caractères composée de lettres, nombres et symboles spéciaux (métacaractères) définissant un motif ("pattern") qui est utilisé pour la recherche de chaînes dans un texte ("pattern matching"). On utilise notamment les expressions régulières dans les outils Unix : grep, egrep, vi, ex, ed, sed, awk, perl...

Attention : les caractères spéciaux des expressions régulières sont assez similaires mais pas entièrement identiques aux métacaractères utilisés par les shells dans l'expansion des noms de fichier.

Caractères spéciaux utilisés dans expressions régulières :

.
Match exactement 1 occurence de n'importe quel caractère
*
Match 0, 1 ou plusieurs fois la sous-expression qui précède. Exemples :
a* = match 0, 1 ou plusieurs fois le caractère "a"
.* = match 0, 1 ou plusieurs fois n'importe quel caractère
^
Placé au début d'une expression régulière, ce symbole représente un début de ligne
$
Placé à la fin d'une expression régulière, ce symbole représente une fin de ligne
[ ]
Match une occurence de l'un des caractères inclus
[^ ]
Match une occurence de n'importe quel caractère autre que celui suivant le "^"
|
(dans awk et egrep uniquement) Séparateur entre deux choix
( )
(dans awk et egrep uniquement) Délimite un ensemble d'expressions régulières
&
(dans sed et ex uniquement) Au niveau d'une pattern de remplacement, réutilise la pattern recherchée
?
(dans awk et egrep uniquement) Match 0 ou 1 instance de l'expression régulière qui précède
+
(dans awk et egrep uniquement) Match 1 ou plusieurs instances de l'expression régulière qui précède
\
Caractère d'échappement : annule l'effet du caractère spécial qui suit. Outre les caractères ci-dessus, les caractères suivants ont aussi une signification particulières et il peut être utile de les préfixer : / { }
Exemples :


2. Éditeur vi

vi est l'éditeur plein écran standard du monde Unix. Très puissant pour qui le maîtrise bien, il n'est cependant pas très convivial (non orienté souris/menus). Mais c'est l'outil que l'on est certain de trouver sur tous les systèmes Unix, et pour cette raison il est nécessaire d'en connaître les bases d'utilisation.

Pour une introduction à vi, voyez depuis Mosaic notre Aide-mémoire de l'éditeur vi.

Pour un manuel plus détaillé sur vi en anglais, cliquer ici.

Dans l'environnement Unix ENAC-SSIE, on dispose de nombreux autres éditeurs (généralement plus simples d'approche que vi) : textedit, xedit, axe, emacs...


3. tr

Les outils tr, sed, awk, perl présentés ci-dessous sont orientés vers la manipulation et la transformation de fichiers texte. Très utiles lorsqu'il est nécessaire d'effectuer automatiquement des tâches répétitives, ils manipulent le texte en utilisant (sauf tr) la syntaxe des expressions régulières. L'objectif n'est pas de les décrire dans le détail ici, mais de signaler leur existence et les illustrer par quelques exemples.

Commande tr

tr string1 string2 {< fich_entree} {> fich_sortie}
Copie entrée standard {ou fich_entree} sur sortie standard {ou fich_sortie} en substituant des caractères. Les arguments string1 et string2 sont des chaînes de caractères, et tous les caractères de string1 sont "mapés" sur les caractères de string2
tr -d string {< fich_entree} {> fich_sortie}
Détruit les caractères énumérés dans string
Exemples
tr '[A-Z]' '[a-z]' < fichier1 > fichier2
Convertit tous les caractères majuscules de fichier1 en caractères minuscules dans fichier2
tr '\011' ' ' < fichier1 > fichier2
Convertit les caractères <TAB> (code ascii octal 011) de fichier1 en caractères espace (" ") dans fichier2
tr -d '\007\014' < fichier1 > fichier2
Détruit les caractères <BELL> et <FF>


4. sed

sed [Stream EDitor] est l'éditeur "batch" standard du monde Unix. Par opposition à vi (éditeur interactif), il prend ses données d'un pipe ou d'un fichier et applique les commandes d'édition (de type ed) qui ont été spécifiées dans l'appel à sed. Plusieurs commandes sed peuvent aussi être sauvegardées dans un script.

Pour accéder à un petit manuel sur sed en anglais, cliquer ici.

Forme générale d'une commande sed

'{adresse}{,adresse}commande{arguments}'

Exemples

sed 's/[Cc]hien/Médor/g' fich_entree > fich_sortie
Substitue toutes les occurences de Chien ou de chien par Médor
sed 's/#.*$//' fich_entree > fich_sortie
Détruit toutes les fins de lignes qui commencent par le caractère #
sed '/^[#!]/d' fich_entree > fich_sortie
Détruit toutes les lignes commençant par # ou par !
sed '/[0-9]/!d' fich_entree > fich_sortie
Détruit toutes les lignes ne contenant pas (!) un chiffre
sed 'x,yd' fichier | more
Affiche fichier sauf lignes No x à No y ($ pour spécifier dernière ligne)
sed -n '/^BEGIN/,/^END/p' fichier
Affiche lignes se trouvant entre lignes BEGIN et END (inclues)
sed -e '/Tartempion/r adresse' -e '/Dupond/w reference' entree > sortie
Insère contenu du fichier adresse aprés chaque ligne contenant Tartempion, et sauve sur fichier reference toutes les lignes contenant Dupond
sed -f fich_commandes_sed ...
Exécution des commandes sed se trouvant dans fich_commandes_sed


5. awk

Egalement outil standard Unix, awk [du nom de ses auteurs : Aho, Weinberger et Kernighan] est un véritable langage orienté vers la manipulation d'enregistrements et de champs (entités plus fines que les lignes manipulées par sed). Les séparateurs d'enregistrements sont les caractères newline, les séparateurs de champs sont les espaces ou tabulations, mais ces séparateurs peuvent être redéfinis.

Voir aussi les commandes Unix cut et paste qui permettent des manipulations simples de type awk.

Pour accéder à un petit manuel sur awk en anglais, cliquer ici. On recommande l'usage de la dernière version nawk [New AWK], voire gawk [GNU/POSIX AWK].

Principe de travail de awk

      Pré-traitement               (groupe BEGIN)
            |
      Ouvrir fichier
            |-----------<-----
            v                 |
   Lecture enregistrement     |
            |                 ^
       Traitement             |
            |                 |
      Fin fichier ? ---non----
            |
    Fermeture fichier
            |
     Post-traitement                (groupe END)
Forme assez générale d'un script awk
(Attention, les accolades {} font ici partie de la syntaxe awk et ne décrivent pas des paramètres optionnels)

'BEGIN {pré-traitement} ; {traitement des enregistrements} ; END {post-traitement}'

Variables

On peut notamment se référer aux variables intégrées suivantes :

Par exemple :

Exemples

nawk '{print $1 "\t" $5 , $2 $4}' fich_entree
Les champs 1, 5, 2 et 4 de fich_entree sont affichés:
- avec <TAB> comme séparateur entre 1 et 5,
- le séparateur par défaut (<SPACE>) entre 5 et 2,
- et le champ 4 est collé à la suite du champ 2
nawk '/chaîne/ {print $4}' fich_entree
Affichage du 4e champ des lignes contenant chaîne
nawk '{total += $6; print $0} ; END {print "total =", total}' fichier
Affiche toutes les lignes du fichier en calculant le total du champ 6 qu'il affiche à la fin du déroulement
nawk '{if ($3 > 41) print NR, $1}' fichier
Pour les lignes où 3e champ > 41, affiche No de ligne suivi de 1er champ
nawk 'BEGIN {FS=":";OFS="\t"} ; {print $1,$2}' fichier
Redéfini caractère ":" comme séparateur de champ en entrée et <TAB> en sortie...
nawk -F : '{print $1 "\t" $2}' fichier
Même résultat que commande précédente
nawk '{printf("No point: %6s %12.3f %12.3f %10.3f \n", $1, $2, $3, $4)}' fichier
Sortie formatée (ici : chaîne constante "No point", puis string formatée à 6 car, puis deux réels formatés 12.3, un réel formaté 10.3, et un <newline> pour le passage à la ligne suivante)
nawk -f programme_awk {-v param=valeur} fichier
Exécution des commandes awk se trouvant dans le fichier programme_awk {avec passage éventuel de paramètre(s) à ce programme}
Autres possibilités ...mais aussi en Shell

Il est aussi possible de manipuler en Shell-script des fichiers-texte découpés en champs. Voici un petit exemple en Bourne-Shell :

      #!/bin/sh
      .....
      old_IFS="$IFS"
      IFS="<TAB>"          # redéfinition du caractère séparateur de champs
      cat mon_fichier | while read un deux trois quatre cinq six sept
      do
        echo "$six"        # affiche le sixième champ de la ligne courante
      done
      IFS="$old_IFS"       # rétablissement du caractère séparateur de champs
      .....


6. perl

perl [practical extraction and report language] est un outils extrêmement riche orienté vers la manipulation de données, de fichiers, la génération de rapports... Développé par Larry Wall, cet outil est dans le domaine public. C'est une combinaison des outils Bourne-shell, sed, awk et langage C. Perl compile ses scripts avant de les exécuter. Perl peut être appelé depuis langage de 3e génération (C, etc...) et vice-versa. C'est un outil orienté vers l'efficacité et la richesse fonctionnelle plutôt que l'élégance... et de ce fait relativement complexe à maîtriser. Il existe des utilitaires de conversion de scripts comme "a2p" (awk -> perl) et "s2p" (sed -> perl).

Pour davantage de détails, voir p.ex. ce site "Perl Resources".


7. Compilateurs

Principes de base

Un programme est écrit dans un langage dit évolué de 3e génération (Pascal, C, Fortran...). Pour être utilisé, il doit être traduit en code objet (compilation) puis en code exécutable (édition de lien). Illustrons ces différentes étapes par quelques exemples issus du Pascal (le principe et les options sont les mêmes avec C ou Fortran) :
pc program.p
Compilation du programme Pascal program.p et lancement automatique de l'édition de lien ("loader" ld) conduisant, dans ce cas, à la création d'un exécutable a.out dans le répertoire courant
pc -o prgm program.p
Compilation du programme program.p et création de l'exécutable prgm par l'éditeur de lien
pc -o prgm prog_princ.p sous_prog.p
Compilation des 2 fichiers prog_princ.p et sous_prog.p et création d'un exécutable prgm. (Les modules objets générés par le compilateur sont automatiquement détruits aprés l'édition de liens).

pc -c prog_princ.p
pc -c sous_prog.p
ld -o prgm prog_princ.o sous_prog.o {librairies...}

L'ensemble de ces 3 commandes conduit au même résultat que la commande précédente : on passe simplement par les étapes intermédiaires suivantes :
  1. Compilation séparée de prog_princ.p sans création d'exécutable mais génération d'un fichier objet prog_princ.o
  2. Compilation séparée de sous_prog.p générant objet sous_prog.o
  3. Edition de lien des 2 modules objets et génération de l'exécutable prgm. A la place de ld, on aurait pu mettre pc, ce qui est en fait préférable, car pc ajoute automatiquement les librairies adéquates (et dans la bonne séquence).
pc -o prgm prog_princ.o sous_prog.p
Recompilation de sous_prog.p seulement, puis création de l'exécutable prgm
Il est possible de linker entre eux des modules objets provenant de différents langages (Pascal, C, Fortran...). Il est cependant important que les types des variables passées correspondent exactement.

Les fichiers exécutables créés par l'éditeur de lien ont automatiquement le droit d'accès execute (x). On peut donc exécuter un programme en frappant directement son nom. Rappel : il ne faut bien entendu jamais imprimer un exécutable (instructions machine en code binaire illisible).

Options de base des compilateurs

Définition de noms de fichiers :
-o nom_executable
Définition du nom de l'exécutable (sinon a.out). (Cette option est passée à l'éditeur de liens ld).
Compilation :
-c
Compilation séparée ne générant que module objet (pas d'appel à ld pour génération d'exécutable)
-w
Suppression des messages de type avertissements (warnings) lors de la compilation
-O{n}
Production de code optimisé (meilleures performances à l'exécution, mais compilation plus longue). Sur Sun, si n=3, optimisation standard. Si n=4, optimisation maximum. Si on ne donne pas n, c'est équivalent à n=3
-C
Génération automatique de code supplémentaire par le compilateur pour tester les dépassements de bornes à l'exécution (attention : autre signification de l'option -C pour le compilateur C)
-g
Production table de symboles augmentée (variables, etc...) pour usage du debugger. Si on donne option -g en faisant compilation séparée, ne pas oublier de donner aussi cette option au moment de l'édition de liens !
-v
Indique ordre de compilation des fichiers
Accès à ressources externes :
-llibrairie
Option passée à ld pour édition de lien avec librairie de nom liblibrairie.a (recherchée dans les répertoires pointés par la var. d'environnement LD_LIBRARY_PATH : principalement /lib, /usr/lib et /usr/local/lib...). A passer en principe après tous les autres paramètres pour que les références soient proprement résolues. (Notes : Les librairies sont créées avec commandes ar [archive] et ranlib. Une librairie n'est pas linkée dans sa totalité, par op. à un fichier .o).
-Lpath
Option passée à ld pour recherche des librairies dans répertoire privé path (avant d'aller dans /lib...)
-Ipath
Option passée au pré-processeur indiquant nom du répertoire où chercher fichiers d'inclusion définis dans code source par : #include "fichier".
Nécessaire seulement si ces fichiers ne sont ni dans /usr/include ni dans le répertoire courant.
Divers :
-help
Donne la liste de toutes les options du compilateur (voir aussi "man compilateur")
-v
Affiche version du compilateur...

Création de librairies

ar -r librairie module(s)_objet
Ajoute ou remplace module(s)_objet à librairie
ar -t librairie
Affiche contenu de librairie

Pascal

Quelques options spécifiques du compilateur Pascal :

-L
Conversion majuscule -> minuscule (mots-clés et identificateurs)
-H
Génération automatique de code de test de validité des pointeurs
-Z
Initialise variables locales à zéro
-s{i}
Vérifie conformité par rapport au standard ISO. Si i=0 : conformité Level 0. Si i=1 ou i pas spécifié : conformité Level 1

C

Fortran

Quelques options spécifiques du compilateur Fortran :

-w66
Suppression des messages d'avertissement relatifs aux incompatibilités avec Fortran 66
-ansi
Identification de toutes les extensions non ANSI (p.ex. extensions Fortran-VMS)
-i2
Donne aux entiers par défaut (INTEGER) le type INTEGER*2 (16 bits)
-u
Oblige le programmeur à déclarer toutes les variables (comme en Pascal). Le statement IMPLICIT reste autorisé.
-e
Accepte lignes de code source jusqu'à 132 car.


8. make

Principes généraux

Make est un outil qui permet de maintenir la consistance d'un ensemble de fichiers en se basant sur la date/heure de dernière modification de ceux-ci. Son utilité s'étend à de nombreux domaines, bien qu'il soit principalement utilisé dans le développement logiciel où il permet de ne faire recompiler que les modules modifiés depuis la dernière compilation d'un projet.

Pour accéder à un petit manuel sur make en anglais, cliquer ici.

La commande make lit dans le répertoire courant le contenu du fichier makefile (ou Makefile) qui contient les règles de dépendance entre les fichiers du projet. Elle en fait un arbre de dépendance sur lequel elle évalue si un fichier dépend d'un autre plus récent que lui, auquel cas les actions prévues sont entreprises.

Un fichier makefile est fait de cibles, de dépendances et de règles (commandes construisant cibles à partir des dépendances). Sa syntaxe est la suivante :

    fichier_cible: fichier_dépendant1 {fichier_dépendant2...}
    <TAB>commande1_Unix
    <TAB>commande2_Unix
    ...
    {#commentaire}

Une telle notation défini que fichier_cible est créé à partir de fichier_dépendant1, fichier_dépendant2... Il doit donc être plus récent qu'eux. Dans le cas contraire (plus ancien ou inexistant), il y (re)création de la cible par exécution des commandes commande1_Unix, commande2_Unix... spécifiées.

Make travaille récursivement : les fichiers fichier_dépendant1, fichier_dépendant2... peuvent être eux-même cibles dans d'autres règles définies dans le même makefile. L'ordre dans lequel les règles sont définies dans le makefile n'a pas d'importance. Chaque commande du makefile est exécutée dans un Bourne-shell différent (=> les mettre sur la même ligne séparées par ";" si on veut les exécuter dans le même shell, p.ex. si on fait un cd suivi d'une commande).

On peut aussi faire usage de macros, mécanisme intéressant notamment pour fixer des options de compilation. La syntaxe est la suivante : NOM_MACRO = chaîne_de_texte
On fait ensuite simplement usage de la macro plus loin dans le makefile en l'invoquant par : $(NOM_MACRO)
On peut aussi passer les valeurs des macros en paramètres lors du lancement de la commande make.

En définissant dans makefile la variable :
VPATH=dir1:dir2:...:dirn
on autorise make à chercher également ses fichiers en dehors du répertoire courant (dans répertoires dir1, dir2...). Utile lorsque les différents modules d'une application sont répartis dans différents répertoires, ou lorsque des applications différentes font appel à des modules identiques.

On défini souvent des cibles spéciales ne correspondant pas à des noms de fichiers mais à des tâches particulières, par exemple :

     clean:
     <TAB> rm *.o
     install:
     <TAB> {déplace les exécutables dans répertoire définitifs et
     <TAB>  positionne les droits d'accès appropriés...}

Dans le cas ci-dessus, la commande "make clean" effacera tous les binaires relogeables, et "make install" installera les exécutables à l'endroit approprié.

Nous ne présentons pas ici les notions de règles implicites et de cibles spéciales.

Usage de la commande make

make {options} {fichier_cible}
Exécute les commandes appropriée du fichier makefile afin de mettre à jour la première cible définie dans ce fichier {ou mettre à jour la cible fichier_cible spécifiée}
-n = liste les commandes qui seraient exécutées sans les exécuter (test makefile)
-i = ignore codes d'erreur (n'interrompt pas exécution...)
-d = affiche les raisons pour lesquelles il effectue les commandes
NOM_MACRO=valeur : passage de valeur à NOM_MACRO

Exemple

Soit le programme Pascal composé du fichier principal.p suivant :
      PROGRAM prgm;
      VAR  a, b: REAL;
      PROCEDURE racine (p: REAL; VAR r: REAL); EXTERNAL;
      BEGIN
         WRITE  ('Donnez un nombre positif : '); READLN (a);
         racine (a, b);
         WRITELN ('La racine de ce nombre est : ',b:10:3);
      END.
et du fichier secondaire.p suivant :
      PROCEDURE racine (p: REAL; VAR r: REAL);
      BEGIN
         r := SQRT(p);
      END ;
Pour construire l'exécutable prgm, on constitue le makefile suivant :
      # Makefile de construction de "prgm"
      # Ci-dessous : options de debugging (les activer en enlevant # dans les 2 lignes qui suivent)
      #DEB_C = -g -C
      #DEB_L = -g
      # Ci-dessous : options d'optimisation (à activer en enlevant #)
      #OPT= -O
      #
      prgm: principal.o secondaire.o
      <TAB>pc $(DEB_L) -o prgm principal.o secondaire.o
      principal.o: principal.p
      <TAB>pc -L -c $(DEB_C) $(OPT) principal.p
      secondaire.o: secondaire.p
      <TAB>pc -L -c $(DEB_C) $(OPT) secondaire.p
      clean:
      <TAB>\rm *.o
On peut alors utiliser ce makefile avec les commandes :


9. Debugger

Le debugger symbolique dbx est un utilitaire permettant d'analyser le comportement d'un programme au moment de l'exécution ou de trouver les raisons pour lesquelles il a "planté" (analyse du fichier core). On parle de "source-level symbolic debugging" car on arrive à manipuler les variables à partir de leur nom symbolique tel que défini dans le code source, et se référer aux Nos de ligne de programme.

Pour fonctionner, dbx a besoin que tous les modules du programme aient été compilés avec l'option -g et que l'édition de liens aie aussi été faite avec cette option. La plupart des environnements interdisent en outre d'utiliser l'option d'optimisation -O lorsque l'on fait du debugging

Il existe sur Sun une interface graphique conviviale au debugger, l'application debugger, et, dans le monde X-window en général, l'application xdbx. Certains utilisent aussi le debugger gdb du GNU.

Initialisation dbx

dbx nom_executable {core}
Lance debugger dbx sur programme exécutable spécifié {avec chargement fichier core-dump si le programme a précédemment planté}. dbx commence par exécuter prologue .dbxinit dans répertoire courant ou répertoire home
-r = démarre immédiatement exécution
-c fichier = exécute commandes d'initialisations de dbx se trouvant dans fichier spécifié

Commandes dbx de base

help
Aide sur dbx
run {options_programme} {parametres_programme}
Lance exécution jusqu'au prochain breakpoint
step {n}
Exécution {n} prochaine(s) instruction(s) (pas-à-pas également dans sous-programmes)
next {n}
Exécution {n} prochaine(s) instruction(s), mais si appel à un sous-programme : exécution de celui-ci dans son entier
cont
Continue exécution jusqu'au prochain breakpoint
where
Affiche position à laquelle programme a planté et stack-trace indiquant comment on y est parvenu
list {ligne_i{,ligne_j}}
Liste 10 prochaines lignes fichier source {de ligne_i à ligne_j}. Position courante marquée par signe ">"
file {fichier}
func {sous_programme}
Indique nom fichier-source courant {ou change de fichier-source}, respectivement indique nom sous_programme courant {ou change de sous_programme}
stop at no_ligne {if condition}
stop in sous_programme {if condition}
stop variable {if condition}
stop if condition
Défini breakpoint (marqué par signe "-") : juste avant d'atteindre no de ligne programme, avant d'entrer dans sous-programme, lorsque variable change d'état, lorsque condition remplie (p.ex. I > 10)
trace no_ligne {if condition}
trace expression at no_ligne {if condition}
trace variable {in sous_programme} {if condition}
trace fonction in fonction
Trace l'exécution d'une variable, d'une fonction, d'une expression
status
Liste Nos de breakpoint ou de trace définis
delete No {, No...}
delete all
Détruit breakpoint ou trace de No spécifié
print variable {, variable...}
Affiche valeur courante des variables spécifiées
display variable {, variable...}
Chaque fois qu'il y a pause dans l'exécution du programme, affichage valeur des variables spécifiées
undisplay variable {variable...}
Cesse affichage des variables spécifiées
dump {sous_programme}
Affiche valeurs de toutes les variables du sous-programme ou de la fonction courante {ou spécifié}
whatis variable
Affiche type d'une variable, ou déclarations d'une fonction ou d'un sous-programme
whereis nom_variable
Indique où est définie variable ou fonction
assign variable = expression
Assigne expression à une variable.
Le nom complet d'une variable est `module`sous_programme`nom (voir commande which variable)
call fonction(arguments...)
Exécute fonction ou sous-programme
sh commande_unix
Exécute commande_Unix dans un C-shell
quit ou exit
Sort de dbx


10. Outils Workshop (SPARCworks/ProWorks)

L'environnement de développement Workshop de SunSoft est disponible sur Sun SPARC (sous le nom SPARCworks) et sur Intel et PowerPC (sous le nom ProWorks). Il est en cours de portage sur d'autres plateformes (HP, Alpha...).

Il est composé des outils suivants (version 3) :

Sous l'appellation TeamWare sont regroupés les outils VersionTool, CodeManager et FreezePoint.


© Jean-Daniel BONJOUR, ENAC-IT, EPF-Lausanne. Révision: 24.11.97.