Langages de scripts, automatisation de commandes et
production de documents structurés :
2. Les précurseurs : Awk et Rexx
gilles.hunault "at" univ-angers.fr
Table des matières cliquable
1. AWK : compter les lignes d'un seul fichier
2. AWK : compter les fichiers par extension
3. AWK : créer les fichiers dictionnaires d'un texte
4. REXX : commandes en session interactive
5. REXX : implémenter range un peu comme en python
6. REXX : exécuter le même programme AWK sur un ensemble de fichiers
7. REXX : archivage incrémental de fichiers XML
Il est possible d'afficher toutes les solutions via ?solutions=1.
1. AWK : compter les lignes d'un seul fichier
La commande wc d'Unix, avec l'option -l permet de connaitre le nombre de lignes d'un ou plusieurs fichiers, comme le montre la commande suivante :
$gh> wc -l demo*.txt 75 demo1_res.txt 9 demo1.txt 40 demo_perl.txt 100 demo_php.txt 61 demo_rexx.txt 75 demo_r.txt 360 totalOn voudrait la compléter pour indiquer le nombre de mots moyen par ligne, avec le nombre minimal et maximal de mots. Ainsi, on disposera d'un moyen pour tester si toutes les lignes ont le même nombre de mots. Implémenter un programme AWK qui calcule ces valeurs en plus du nombre de lignes. On devra l'exécuter par la commande gawk -f nblv1.awk fichier mais pour un seul fichier de données. Quel est le défaut de cet appel de programme ? Comment avoir un "help" de ce programme ? On rappelle que pour AWK la variable FNR correspond au numéro de ligne courant dans le fichier, NF au nombre de mots de la ligne courante et FILENAME au nom du fichier. Que se passe-t-il si au lieu d'un seul fichier on utilise une notation ambigue ? Voici un exemple de ce qu'on voudrait obtenir (les espaces et le formatage font partie de l'affichage, voir exercice 6) :
$gh> gawk -f nblv1.awk demo1_res.txt demo1_res.txt 75 ligne(s) NFmoyen 3.23 NFmin 0 NFmax 15*On pourra se contenter dans un premier temps de ne calculer que le nombre moyen de mots, affiché avec deux décimales.
Solution : afficher la solution
Puisque ce programme AWK ne doit s'appliquer qu'à un seul fichier, le programme est très simple à écrire : on initialise les variables quand on lit la ligne 1, on cumule les NF et on met à jour éventuellement les min et max de NC pour les autres lignes et enfin on affiche après avoir lu la dernière ligne du fichier. On peut utiliser NFR en fin de programme comme nombre de lignes lues pour calculer la moyenne des NC. Voici un exemple de programme minimal possible nommé nblv0.awk :
# (gH) -_- nblv0.awk ; TimeStamp (unix) : 17 Novembre 2012 vers 22:24 END{ # j'adore commencer par END ! printf("Fichier %s avec %d ligne(s), NF moyen = %8.2f \n", FILENAME, FNR, nc/FNR ) } # fin de END (FNR==1) { nc = NF } # ligne 1 du fichier, on initialise nc qui est le nombre de mots en tout (FNR> 1) { nc += NF } # après la première ligne, on cumule les NF dans nc$gh> gawk -f nblv0.awk demo1_res.txt Fichier demo1_res.txt avec 75 ligne(s), NF moyen = 3.23Sur ce principe, et en remettant END "à sa place" on peut compléter avec le nombre minimal et maximal de mots par ligne soit le fichier nblv1.awk :
# (gH) -_- nblv1.awk ; TimeStamp (unix) : 17 Novembre 2012 vers 22:24 # nblv1.awk : nombre de lignes pour un seul fichier en principe (ou globalisation pour plusieurs) BEGIN { nc = 0 } # nc = nombre de champs = nombre de mots par ligne # ligne 1 du fichier, on initialise les variables : # nc est le nombre de mots en tout # pnc est le nombre minimal de mots par ligne (p=petit) # gnc est le nombre maximal de mots par ligne (g=grand) (FNR==1) { nc = NF ; pnc = NF ; gnc = NF } # après la première ligne, on cumule nc et on met à jour éventuellement pnc et gnc (FNR> 1) { nc += NF ; if (NF<pnc) { pnc = NF } ; if (NF>gnc) { gnc = NF } ; } # fin de ligne >1 # en fin de fichier, on affiche les résultats END{ if (pnc==gnc) { cc =" " } else { cc = "*" } if (FNR==0) { ncr = 0 } else { ncr = nc/FNR } # fin de si printf(" %-30s %5d ligne(s) NFmoyen %8.2f NFmin %4d NFmax %4d", FILENAME, FNR, ncr, pnc, gnc ) print(cc) # si * : toutes les lignes n'ont pas le meme nombre de champs } # fin de ENDLe défaut de ce programme est de ne pas gérer plusieurs fichiers à la fois. Si on l'applique à un ensemble de fichiers, il fournira un résultat erroné et n'affichera que des informations -- correctes, mais incomplètes -- pour le dernier fichier. Pour l'appliquer en boucle sur chacun des fichiers passés en paramètre, voir l'exercice numéro 6.
Il n'est pas possible d'avoir de "help" sauf à "bricoler". Par exemple en admettant que le fichier HELP_nbl.awk_AIDE sert à reconnaitre qu'on veut connaitre l'aide, on pourrait écrire quelque chose comme le le fichier nblv1aide.awk :
# (gH) -_- nblv1aide.awk ; TimeStamp (unix) : 17 Novembre 2012 vers 23:03 # nblv1aide.awk : nombre de lignes pour un seul fichier en principe (ou globalisation pour plusieurs) # on affiche l'aide si on applique le programme au fichier HELP_nbl.awk_AIDE BEGIN { nc = 0 } # nc = nombre de champs = nombre de mots par ligne # ligne 1 du fichier, on initialise les variables : # nc est le nombre de mots en tout # pnc est le nombre minimal de mots par ligne (p=petit) # gnc est le nombre maximal de mots par ligne (g=grand) (FILENAME=="HELP_nbl.awk_AIDE") { # aide du programme print " nblv1aide.awk : ce programme... \n" exit } # fin si (FNR==1) { nc = NF ; pnc = NF ; gnc = NF } # après la première ligne, on cumule nc et on met à jour éventuellement pnc et gnc (FNR> 1) { nc += NF ; if (NF<pnc) { pnc = NF } ; if (NF>gnc) { gnc = NF } ; } # fin de ligne >1 # en fin de fichier, on affiche les résultats END{ if (pnc==gnc) { cc =" " } else { cc = "*" } if (FNR==0) { ncr = 0 } else { ncr = nc/FNR } # fin de si printf(" %-30s %5d ligne(s) NFmoyen %8.2f NFmin %4d NFmax %4d", FILENAME, FNR, ncr, pnc, gnc ) print(cc) # si * : toutes les lignes n'ont pas le meme nombre de champs } # fin de ENDEncore faudra-t-il savoir qu'il faut appeler le programme sur ce fichier via gawk -f nblv1aide.awk HELP_nbl.awk_AIDE.
En fait, très souvent on n'appelle pas un programme AWK directement. On utilise un script du système qui teste les paramètres et affiche l'aide si aucun paramètre n'est fourni et qui sinon exécute le programme avec le "bon" chemin d'accès (voir l'exercice 6).
2. AWK : compter les fichiers par extension
On aimerait connaitre le nombre de fichiers par extension, avec la taille qu'ils occupent. Ecrire un programme Awk pour réaliser cela. Voici un exemple de ce qu'on voudrait obtenir pour notre répertoire courant (affichage trié) :
--- ext nb_fich cumul_taille (kO) 2012 1 1 aux 1 0 awk 13 9 awk_AIDE 1 0 b 1 0 css 1 0 dac 1 0 dsc 1 7 dvi 1 1 gal 1 0 gif 2 0 htm 1 6 html 2 0 html.old 1 0 jpg 4 2028 js 2 19 log 1 6 m1 1 1 ngr 1 0 noacc 1 0 ocd 1 0 ocm 1 0 pdf 1 11 personnes 1 0 php 19 173 php.old 7 105 pl 6 24 pl.old 1 9 png 16 1685 ps 1 80 py 7 18 pyc 1 0 r 2 494 rb 1 0 rex 15 47 rnc 1 2 rtf 1 11 sedit 2 3 sh 1 0 sor 2 12 tar 2 20 tcl 3 21 tex 1 1 tk 1 1 tmp 1 0 txt 69 1060 xml 2 1 zip 1 4240 soit en tout 208 fichiers et 9.88 MoSolution : afficher la solution
Consulter le fichier statdir.awk pour une version proche de la solution, et qui s'utilise par exemple par ls -al | gawk -f statdir.awk :
# statdir.awk : gestion de répertoire (nb de fichiers par extension) BEGIN { nbf = 0 } /-/ && $1 !~ /^d/ && $8 != "dir.dir" { ip = index($8,".") if (ip > 0) { ext = substr($8,1+ip) } else { ext = "???" } tot[ext] += $5 ; nb[ext] ++ ; nbf++ ; tgen += $5 } # fin de traitement des lignes retenues END { print "--- ext nb_fich cumul_taille (kO)" for (ext in tot) { printf (" %-15s %3d %12d\n" , ext , nb[ext] , tot[ext]/1024 ) } # fin de pour if (nbf==0) { print " mais je n'ai vu aucun fichier !! "} else { tgen = tgen/(1024*1024) print " soit en tout " sprintf("%7d",nbf) " fichiers et " sprintf("%5.2f",tgen) " Mo " } } # fin du ENDIl reste juste à trier l'affichage, ce que nous laissons à la perspicacité des lecteurs et lectrices.
3. AWK : créer les fichiers dictionnaires d'un texte
On aimerait construirer les dictionnaires alphabétiques et fréquentiels du fichier texte.txt dont le contenu est :
Ceci est un petit texte dont le but est de tester la création de dictionnaires avec un langage de script. C'est pourquoi il est court -- et peu intéressant ! -- mais c'est un fichier pratique ; on conserva les accents tels quels.Voici ce qu'on voudrait obtenir comme dictionnaire alphabétique, soit le fichier dico.tpm :
C 1 Ceci 1 accents 1 avec 1 but 1 c 1 conserva 1 court 1 création 1 de 3 dictionnaires 1 dont 1 est 5 et 1 fichier 1 il 1 intéressant 1 la 1 langage 1 le 1 les 1 mais 1 on 1 petit 1 peu 1 pourquoi 1 pratique 1 quels 1 script 1 tels 1 tester 1 texte 1 un 3Et voici ce qu'on voudrait obtenir comme dictionnaire fréquentiel, soit le fichier dico.tpo. Il faut donc trier ici par fréquence décroissante puis par ordre alphabétique croissant en cas d'exaequo :
est 5 de 3 un 3 C 1 Ceci 1 accents 1 avec 1 but 1 c 1 conserva 1 court 1 création 1 dictionnaires 1 dont 1 et 1 fichier 1 il 1 intéressant 1 la 1 langage 1 le 1 les 1 mais 1 on 1 petit 1 peu 1 pourquoi 1 pratique 1 quels 1 script 1 tels 1 tester 1 texte 1Solution : afficher la solution
Consulter le fichier dico.awk pour une version proche de la solution :
# dico.awk BEGIN { fs = "tmp.tmp" } (FNR==1) { print " Traitement des mots dans : " FILENAME } { nbl ++ # comptage des lignes gsub(/[\"',.%#/]/ , " ") # filtrage des séparateurs gsub(/[-();:!]/, " ") # élmination de la ponctuation for (i=1;i<=NF;i++) { ++mot[ $i ] } # comptage des mots nbm += NF } # fin du traitement de chacune des lignes END { for (x in mot) { if (length(x)>35) { x = substr(x,1,35) } printf("%-40s %6d\n", x , mot[x]) > fs nbmd++ } # fin pour close(fs) fmot = "dico.tpm" focc = "dico.tpo" system("sort " fs " > " fmot ) system("sort -k 2rn -k 1 " fmot " > " focc ) print " on a vu " nbm " mot(s) sur " nbl " ligne(s) et " nbmd " mots différents " print " le fichier " fmot " contient les mots par ordre alphabétique " print " le fichier " focc " contient les mots par ordre décroissant d'occurence " } # fin de END
4. REXX : commandes en session interactive
En mode interactif, avec rt.rex donner la ou les instructions qui répondent aux questions suivantes :
quelle est la valeur de 16 puissance 4 ? et le reste entier de la division de 2012 par 128 ?
quel est le code hexadécimal de A ? et le code décimal de 'xFFF' ? et le code ascii de 'a' ? et le caractère de numéro décimal 98 ?
si la variable cmd contient "prog --fmt tex --nbdec 4 --fichier demo.rex" comment récupérer la valeur de l'option --fmt c'est-à-dire tex ?
si phr contient "A2837 12 18 37 25" comment transférer dans la variable numData toutes les valeurs après le premier mot (soit ici A2837) ?
combien vaut factorielle 8 ?
comment afficher ou mettre dans une variable la date et l'heure ?
comment calculer la moyenne des valeurs contenues dans la chaine de caractères "12 5 20 8 15" ?
comment souligner avec des tirets la chaine de caractères "ceci est mon titre" ?
Solution : afficher la solution
Voici un exemple de solution en session interactive :
$gh> rt REXX-Regina_3.3(MT) 5.00 25 Apr 2004 REXX statements / exit / <enter> : Rexx> say 16**4 2012//128 65536 92 Rexx> say c2x("A") x2d('FFF') c2d("a") d2c(98) 41 4095 97 b Rexx> cmd = "prog --fmt tex --nbdec 4 --fichier demo.rex" Rexx> parse var cmd "--fmt" valFmt . Rexx> say valFmt tex Rexx> phr = "A2837 12 18 37 25" Rexx> parse var phr . numData ; say numData 12 18 37 25 Rexx> f=1 ; do i=2 to 8 ; f= f*i ; end ; say f 40320 Rexx> call charout , date() " et " ; dt = date("E") time() ; say dt 18 Nov 2012 et 18/11/12 11:56:52 Rexx> v = "12 5 20 8 15" Rexx> s = 0 Rexx> do i=1 to words(v) ; s = s + word(v,i) ; end Rexx> say s/words(v) 12 Rexx> ti = "ceci est mon titre" Rexx> say ti ; say copies("-",length(ti)) ceci est mon titre ------------------ Rexx> exit
5. REXX : implémenter range un peu comme en python
Implémenter une fonction range() en REXX un peu comme Python, mais en commençant à l'indice 1. On viendra compléter le fichier range.rex suivant qui indique ce qu'on veut obtenir :
/* (gH) -_- range.rex ; TimeStamp (unix) : 18 Novembre 2012 vers 10:40 */ /* implémentation de la fonction range de python en rexx */ a = range(5) /* doit renvoyer 1 2 3 4 5 */ say a say range(10,15) /* doit afficher 10 11 12 13 14 15 */ say range(10,20,4) /* doit afficher 10 14 18 */Solution : afficher la solution
Dans la mesure où REXX dispose d'une boucle do / = / to / by / end le problème est juste de bien gérer les paramètres, ici séparés par des virgules, d'où le fichier solution range_sol.rex :
/* (gH) -_- range_sol.rex ; TimeStamp (unix) : 18 Novembre 2012 vers 10:55 */ /* implémentation de la fonction range de python en rexx */ a = range(5) /* doit renvoyer 1 2 3 4 5 */ say a say range(10,15) /* doit afficher 10 11 12 13 14 15 */ say range(10,20,4) /* doit afficher 10 14 18 */ exit(0) /* code-retour 0 : tout va bien */ /* implémentation de la fonction range */ range: parse arg debut , fin , pas leRange = "" if pas = "" then do pas = 1 end /* finsi */ if fin = "" then do fin = debut debut = 1 end /* finsi */ do ival=debut to fin by pas leRange = leRange ival end /* fin de pour */ return leRange$gh> regina range_sol.rex 1 2 3 4 5 10 11 12 13 14 15 10 14 18Pour ceux et celles qui préfèrent une séparation des paramètres par des espaces, consulter range_sol1.rex.
6. REXX : exécuter le même programme AWK sur un ensemble de fichiers
Reprendre l'exercice 1. On utilisera REXX pour afficher un "help" si on ne fournit aucun paramètre ; sinon, on exécutera la commande gawk -f nblv2.awk sur chacun des fichiers passés en paramètre (notation ambigue avec * et ? possible).
Solution : afficher la solution
Là encore, il s'agit juste de bien gérer les paramètres. On remarquera dans la solution la composition "à la volée" de la commande à exécuter.
/* (gH) -_- nbl.rex ; TimeStamp (unix) : 18 Novembre 2012 vers 11:19 */ /* on exécute gawk -f nblv2.awk sur chaque fichier passé en paramètre */ /* (expression ambigue avec * et ? ok) */ parse arg lig /* rappel éventuel de la syntaxe */ if words(lig)=0 then do say " nbl[.rex] : nombre de lignes et nombre de mots par fichier" say say " syntaxe : nbl nom_de_fichier(s)" say " exemple : nbl demo*txt " say exit(-1) ; end /* fin de si */ /* exécution de la commande sur chaque fichier */ cmd = "gawk -f nblv2.awk " do i = 1 to words(lig) cmd word(lig,i) end /* fin pour */# nblv2.awk : nombre de lignes pour un fichier (ou globalisation pour plusieurs) BEGIN { nc = 0 } # nc = nombre de champs = nombre de mots par ligne # ligne 1 du fichier, on initialise les variables : # nc est le nombre de mots en tout # pnc est le nombre minimal de mots par ligne (p=petit) # gnc est le nombre maximal de mots par ligne (g=grand) (FNR==1) { nc = NF ; pnc = NF ; gnc = NF } # après la première ligne, on cumule nc et on met à jour éventuellement pnc et gnc (FNR> 1) { nc += NF ; if (NF<pnc) { pnc = NF } ; if (NF>gnc) { gnc = NF } ; } # fin de ligne >1 # en fin de fichier, on affiche les résultats END{ if (pnc==gnc) { cc =" " } else { cc = "*" } if (FNR==0) { ncr = 0 } else { ncr = nc/FNR } # fin de si printf(" %-30s %5d ligne(s) NFmoyen %8.2f NFmin %4d NFmax %4d", FILENAME, FNR, ncr, pnc, gnc ) print(cc) # si * : toutes les lignes n'ont pas le meme nombre de champs } # fin de END$gh> regina nbl.rex nbl[.rex] : nombre de lignes et nombre de mots par fichier syntaxe : nbl nom_de_fichier(s) exemple : nbl demo*txt $gh> regina nbl.rex demo*txt demo1_res.txt 75 ligne(s) NFmoyen 3.23 NFmin 0 NFmax 15* demo1.txt 9 ligne(s) NFmoyen 7.56 NFmin 0 NFmax 21* demo_perl.txt 40 ligne(s) NFmoyen 3.05 NFmin 0 NFmax 11* demo_php.txt 100 ligne(s) NFmoyen 2.24 NFmin 0 NFmax 11* demo_rexx.txt 61 ligne(s) NFmoyen 2.13 NFmin 0 NFmax 12* demo_r.txt 75 ligne(s) NFmoyen 3.68 NFmin 0 NFmax 11*
7. REXX : archivage incrémental de fichiers XML
On voudrait qu'à l'exécution du script archcd.rex il y ait une production automatique de l'archive pour tous les fichiers de type xml avec numérotation de l'archive. Par exemple la première fois que le script est exécuté, on produira l'archive lesxml001.tar ; la seconde fois, ce sera lesxml002.tar etc. L'algorithme de base ressemble certainement à
# algorithme d'archivage en .tar des *.xml affecter numarchive <-- 1 construire nomarchive à partir de numarchive tant_que le fichier nomarchive existe affecter numarchive <-- numarchive + 1 construire nomarchive à partir de numarchive fin tant_que le fichier nomarchive existe exécuter la commande tar pour les fichiers indiqués afficher un message indiquant que l'archivage est faitSolution : afficher la solution
Consulter le fichier archcd.rex :
/* (gH) -_- archcd.rex ; TimeStamp (unix) : 24 Novembre 2012 vers 20:17 */ numarchive = 1 nomarchive = "lesxml"||rexxut("formatZero^"numarchive"^3")||".tar" do while fileut("existsFile^"nomarchive) numarchive = numarchive + 1 nomarchive = "lesxml"||rexxut("formatZero^"numarchive"^3")||".tar" end /* fin de tant que */ specfic = "*.xml" "tar -cf " nomarchive specfic say "[rex] M1 : OK pour archivage des fichiers " specfic " dans " nomarchiveExemple d'utilisation :
$gh> rm lesxml*.tar $gh> regina archcd.rex [rex] M1 : OK pour archivage des fichiers *.xml dans lesxml001.tar $gh> regina archcd.rex [rex] M1 : OK pour archivage des fichiers *.xml dans lesxml002.tar
8. REXX : que font ces programmes ?
Que fait le programme REXX nommé catv.rex ? Et les macros pour éditeur av.sedit, ts.sedit et exec.sedit ?
Solution : afficher la solution
Après lecture du fichier-programme REXX nommé catv.rex dont nous avons numéroté les lignes,
0001 /* (gH) -_- catv.rex ; TimeStamp (unix) : 24 Novembre 2012 vers 20:21 */ 0002 0003 parse arg f1 f2 nbesp l1max . 0004 0005 if words(f2)=0 then do 0006 say 0007 say " catv : ??? -- titre masqué par (gH) pour exercice M1 info" 0008 say " syntaxe : catv fic1 fic2 [nbesp longueurMax] " 0009 say " exemples : catv a.txt b.txt " 0010 say " catv a.txt b.txt 5 " 0011 say " catv a.txt b.txt 5 70" 0012 say 0013 return 0014 end /* fin de si */ 0015 0016 if nbesp = "" then nbesp = 0 0017 entre = copies(" ",nbesp) 0018 nbl. = 0 0019 lig. = "" 0020 0021 /* lecture des deux fichiers */ 0022 0023 call litf 1 f1 0024 call litf 2 f2 0025 0026 nbl = nbl.1 0027 if nbl.2 > nbl then nbl = nbl.2 0028 0029 /* écriture du fichier résultat */ 0030 0031 fics = "catv.sor" 0032 rf = fileut("delFile^"fics) 0033 0034 do i = 1 to nbl 0035 if l1max="" then do 0036 call lineout fics , lig.1.i entre lig.2.i 0037 end ; else do 0038 call lineout fics , rexxut("surncarg^"l1max"^"lig.1.i) entre lig.2.i 0039 end /* fin si */ 0040 end /* fin de tant que */ 0041 call lineout fics 0042 0043 say " vous pouvez utiliser " fics 0044 return 0045 0046 /* ========== sous-programme ========== */ 0047 0048 litf: parse arg nf nomf 0049 say " lecture " nf " : " nomf 0050 do while lines(nomf)>0 0051 nbl.nf = nbl.nf +1 0052 n = nbl.nf 0053 lig.nf.n = linein( nomf ) 0054 end /* fin de tant que */ 0055 if nbl.nf = 0 then say " attention fichier " nom " vide " 0056 call lineout nomf 0057 returnon peut comprendre que ce programme REXX lit deux fichiers dont les noms sont passés en paramètre (lignes 23 et 24) et qu'il met met bout à bout soit une concaténation verticale (lignes 34 à 40 ) les lignes des deux fichiers. Par exemple, avec les deux fichiers gauche.txt et droite.txt la commande catv gauche.txt droite.txt 3 35 produit le fichier gd2.txt. Si on ne passe pas de paramètre de taille de ligne après les noms de fichier et si le fichier de gauche n'a pas des lignes de même longueur, le résultat est "cahotique" comme pour le fichier gd1.txt. On remarquera l'initialisation des stem (tableaux) ligne 19 qui permet de ne pas se préoccuper de lignes inexistantes...
Fichier de gauche * Awk * Javascript * Perl * Php * Python * R * Rexx et Oorexx, NetRexx * Ruby * Tcl * Tk *Fichier de droite Apl C et C++ Dbase Fortran Java Lisp Logo Prolog Scala SmalltalkFichier de gauche * Fichier de droite Awk * Apl Javascript * Perl * C et C++ Php * Python * Dbase R * Fortran Rexx et Orrex, NetRexx * Java Ruby * Lisp Tcl * Logo Tk * Prolog Scala SmalltalkL'étudiant Hossam Eddine BENHOUD a réussi à trouver une commande Unix à peu près équivalente. Il suffit d'écrire pr -m -t fichier1 fichier2. Bravo Hossam Edine !
La macro-programme REXX pour éditeur nommée av.sedit
0001 /* (gH) -- av.sedit ; TimeStamp (unix) : 02 Février 04 12:14 */ 0002 0003 /* av.sedit : archivage avec incrementation dans ~/Tmp */ 0004 0005 'extract /fname/' 0006 'extract/ftype/' 0007 idp = pos(".",fname) 0008 fnv = 1 0009 do while length(fnv)<4 0010 fnv = "0"||fnv 0011 end 0012 fnom = fname.1 0013 ftyp = ftype.1 0014 if words(fnom)=0 then do 0015 fnom = substr(ftyp,2) 0016 ftyp = "" 0017 end 0018 nn = "~/Tmp/"||fnom||"."||fnv||ftyp 0019 tn = state(nn) 0020 do while tn > 0 0021 fnv = fnv + 1 0022 do while length(fnv)<4 0023 fnv = "0"||fnv 0024 end 0025 nn = "/home/gh/Tmp/"||fnom||"."||fnv||ftyp 0026 tn = state(nn) 0027 end /* fin de tant que */ 0028 nomd = fnom 0029 msg " depose incrémentale en " nn 0030 'ssave ' nomd fnv||ftyp "/home/gh/Tmp/"vient sauvegarder dans le répertoire ~/Tmp une copie du fichier en cours d'édition avec le même nom et de même extension mais avec insertion d'un numéro entier sur 4 positions autoincrémenté. Ainsi pour le fichier s1p2.php l'exécution de la macro, en ligne de commande-éditeur ou avec une touche comme F2 vient sauvegarder le fichier actuel comme s1p2.0001.php ; la seconde exécution produit s1p2.0002.php etc. La fonction state à la ligne 19 et à la ligne 26 renvoie 0 si le fichier n'existe pas, un entier positif sinon.
La macro-programme REXX pour éditeur nommée ts.sedit
0001 /* (gH) -- ts.sedit ; TimeStamp (unix) : 02 Février 2005 vers 10:49 */ 0002 /* ts.sedit : (TimeStamp) "timbre de temps " */ 0003 /* met le nom du fichier, la date et l'heure en haut de fichier */ 0004 0005 /* récupération des marges */ 0006 0007 'extract/margins/' 0008 marg1 = margins.1 0009 marg2 = margins.2 0010 marg3 = margins.3 0011 /* extraction de l'identificateur du fichier */ 0012 0013 'extract /fname/' 0014 'extract/ftype/' 0015 nomfich = fname.1||ftype.1 0016 0017 /* on met la date... */ 0018 0019 parse value date(E) with jr '/' mois '/' an 0020 listemois = 'Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre Décembre' 0021 mois = word(listemois,mois) 0022 0023 txt1 = " (gH) " 0024 txt2 = " ; TimeStamp (unix) :" jr mois "20"||an 0025 0026 /* l'heure... */ 0027 0028 txt2 = txt2 "vers" left(time(),5) 0029 0030 /* ... et le nom du fichier */ 0031 0032 fext = translate(Ftype.1) 0033 if fext = '.HTM' then txt = txt1 " -_- " nomfich txt2 0034 else txt = txt1 " -_- " nomfich txt2 0035 0036 if fext = '.HTML' then txt = txt1 " -_- " nomfich txt2 0037 else txt = txt1 " -_- " nomfich txt2 0038 0039 /* il reste à mettre le(s) symbole(s) de commentaire, */ 0040 0041 0042 if fext = '.ABR' then txt = '# '||txt 0043 if fext = '.AWK' then txt = '# '||txt 0044 if fext = '.BAT' then txt = 'rem '||txt 0045 if fext = '.CMD' then txt = '/* '||txt||' */' 0046 if fext = '.CSS' then txt = '/* '||txt||' */' 0047 if fext = '.JS' then txt = '// ' txt 0048 if fext = '.JAVA' then txt = '// ' txt 0049 if fext = '.HTM' then txt = '<!-- ' txt ' -->' 0050 if fext = '.HTML' then txt = '<!-- ' txt ' -->' 0051 if fext = '.KEX' then txt = '* '||txt 0052 if fext = '.PAS' then txt = '# '||txt 0053 if fext = '.PHP' then txt = '# ' txt 0054 if fext = '.PHP3' then txt = '<!-- ' txt ' -->' 0055 if fext = '.PL' then txt = '# '||txt 0056 if fext = '.PM' then txt = '# '||txt 0057 if fext = '.PRL' then txt = '# '||txt 0058 if fext = '.PRM' then txt = '# '||txt 0059 if fext = '.R' then txt = '# '||txt 0060 if fext = '.REX' then txt = '/* '||txt||' */' 0061 if fext = '.STY' then txt = '% '||txt 0062 if fext = '.MYSQL' then txt = '# '||txt 0063 if fext = '.SQL' then txt = '# '||txt 0064 if fext = '.TCL' then txt = '# '||txt 0065 if fext = '.TEX' then txt = '% '||txt 0066 if fext = '.TEY' then txt = '% '||txt 0067 if fext = '.TK' then txt = '# '||txt 0068 0069 if fext = '.SEQ' then txt = '# '||txt 0070 if fext = '.DPD' then txt = '# '||txt 0071 0072 if fext = '.SEDIT' then txt = '/* '||txt||' */' 0073 if fext = '.XML' then txt = '<!-- '||txt||' -->' 0074 0075 /* à sauvegarder l'ancienne position courante */ 0076 0077 'extract/line/' 0078 oline = line.1 0079 0080 /* à recherche une éventuelle ancienne ligne de TimeStamp */ 0081 0082 ':0' 0083 '/ TimeStamp ' 0084 'extract/line/' 0085 nline = line.1 0086 0087 /* à insérer le texte au bon endroit, */ 0088 0089 'set margins 1 150 1' 0090 if nline=0 then oline = oline+1 0091 if nline>0 then do ; 'delete' ; '-1' ; end 0092 'I' txt 0093 0094 /* à sauvegarder le fichier... */ 0095 0096 'ssave' 0097 0098 /* à remettre les anciennes marges */ 0099 0100 'set marg ' marg1 marg2 marg3 0101 0102 /* et à se repositionner au bon endroit */ 0103 ':'oline 0104 0105 /* et voilà ! */ 0106 'msg'ajoute en haut de fichier une ligne qui donne la date et l'heure. Si la ligne existe déjà, elle est mise à jour. La ligne est insérée comme un commentaire s'il s'agit d'un fichier-programme, avec le format de commenatire lié au langage. Par exemple, appliquée au fichier s1p2.php il y a insertion de quelque chose comme
# (gH) -_- s1p2.php ; TimeStamp (unix) : 11 Septembre 2004 vers 23:24Pour un fichier REXX comme par exemple s1p2.rex, le commentaire sera :
/* (gH) -_- s1p2.rex ; TimeStamp (unix) : 11 Septembre 2004 vers 23:24 */La correction pour exec.sedit n'est volontairement pas fournie.
9. REXX : fichiers dictionnaires d'un texte
Essayer de réaliser l'exercice 3 proposé pour AWK (création des dictionnaires) en REXX.
Solution : afficher la solution
Consulter dico.rex sachant qu'on utilise les bibliothèques de fonctions (gH) nommées FILEUT.rex et REXXUT.rex.
/* (gH) -_- dico.rex ; TimeStamp (unix) : 01 Décembre 2012 vers 23:31 */ parse arg fn . if fn="" then do /* aide éventuelle */ say say " dico.rex ; création des dictionnaires alphabétiques et fréquentiels d'un texte " say say " syntaxe : regina dico.rex FICHIER " say " exemple : regina dico.rex texte.txt" say say " les fichiers produits sont dico.tpm et dico.tpo" say " dico.tpm : tri par mot croissant " say " dico.tpo : tri par fréquence décroissante " ; say " puis par mot croissant an cas d'égalité." exit end /* finsi */ rf = fileut("checkFile^"fn) if rf=-1 then do say say "Fin du programme du à l'absence du fichier. " say exit end /* fin si */ /* si on arrive ici c'est que le fichier existe */ fs1 = "dico.tpm" rf = fileut("deleteFile^"fs1) fs2 = "dico.tpo" rf = fileut("deleteFile^"fs2) say "Traitement des mots dans :" fn /* parcours du fichier, comptage des mots */ nbl = 0 /* lignes */ nbm = 0 /* mots en tout */ nbmd = 0 /* mots différents */ nbo. = 0 /* tableau des comptages */ tdm. = "" /* tableau des mots " */ do while lines(fn)>0 lig = linein(fn) nbl = nbl + 1 /* on vire la ponctuation */ ligp = "" do ic=1 to length(lig) cc = substr(lig,ic,1) select when cc="'" then oc = " " when cc="," then oc = " " when cc="-" then oc = " " when cc="?" then oc = " " when cc="!" then oc = " " when cc="." then oc = " " when cc=";" then oc = " " otherwise oc = cc end /* fin des cas */ ligp = ligp || oc end /* fin pour im */ /* donc maintenant on peut compter les mots */ nbmc = words(ligp) nbm = nbm + nbmc do im=1 to nbmc mot = word(ligp,im) nbo.mot = nbo.mot + 1 if nbo.mot = 1 then do nbmd = nbmd + 1 tdm.nbmd = mot end /* fin si */ end /* fin pour im */ end /* fin tant que */ rf = fileut("closeFile^"fn) verif = 0 /* 0 en normal, 1 en mode debug */ if verif=1 then do idm=1 to nbmd mot = tdm.idm occ =nbo.mot say " mot " idm " = " mot " vu " occ " fois " end /* fin pour idm */ say "On a vu " nbm " mot(s) sur " nbl "lignes et " nbmd " mots différents." /* tri par mots : on les met bout à bout pour profiter de triPhrase */ tlm = "" /* tous les mots */ do idm=1 to nbmd tlm = tlm tdm.idm end /* fin pour idm */ tlmt = rexxut("triPhrase^"tlm) /* on écrit dans fs1 */ do idm=1 to words(tlmt) mot = word(tlmt,idm) occ = nbo.mot call lineout fs1 , rexxut("surncarg^30^"mot) format(occ,5) end /* fin pour idm */ rf = fileut("closeFile^"fs1) say "le fichier " fs1 " contient les mots par ordre alphabétique" /* tri par occurences : on construit des occ_mot que l'on trie via triPhrase */ tlo = "" /* tous les mots */ do idm=1 to nbmd mot = tdm.idm occ = rexxut("formatZero^"nbo.mot"^6") tlo = tlo occ||"_"||mot end /* fin pour idm */ tlot = rexxut("triPhrase^"tlo) /* on écrit dans fs1 en retriant les ex-aequo */ nbop = 0 /* nb d'occurences précédent */ ldm = "" /* liste des mots */ nbmo = words(tlot) do idm=1 to nbmo om = word(tlot,nbmo+1-idm) parse var om occ "_" mot if (idm=1) then do nbop = occ ldm = mot end ; else do if occ=nbop then do ldm = ldm mot end ; else do /* on affiche les précédents et on prépare la nouvelle liste */ call ecritMots fs2 nbop ldm nbop = occ ldm = mot end /* fin si */ end /* finsi on est après le premier mot */ end /* fin pour idm */ /* il faut toujours afficher la dernière liste */ call ecritMots fs2 nbop ldm rf = fileut("closeFile^"fs2) say "le fichier " fs2 " contient les mots par ordre décroissant d'occurences" say exit ecritMots: procedure parse arg fic nboc liste ldmt = rexxut("triPhrase^"liste) do jdm=1 to words(ldmt) motc = word(ldmt,jdm) call lineout fic , rexxut("surncarg^30^"motc) format(nboc,5) end /* finsi */ return/* (gH) -_- FILEUT.rex ; TimeStamp (unix) : 16 Juin 2008 vers 08:22 */ /* */ /******************************************************************************/ /* */ /* */ /* Fichier : FILEUT.rex v-2.7 */ /* */ /* */ /* Gilles.HUNAULT@univ-angers.fr */ /* http://www.info.univ-angers.fr/~gh/ */ /* */ /* */ /* " Sous-programmes rex d'interface avec le systeme " */ /* et de gestion des fichiers " */ /* */ /* */ /******************************************************************************/ /* */ /* Liste des fonctions disponibles : */ /* (attention aux majuscules ! osname est incorrect à cause du n) */ /* */ /* sans paramètres : */ /* */ /* clrscr */ /* cpy */ /* cpyWeb */ /* cpyWeb */ /* uName */ /* versionFu */ /* currentDir */ /* attends */ /* */ /* avec 1 paramètre : */ /* */ /* baseName */ /* delFile */ /* deleteFile */ /* pathName */ /* seeFile */ /* checkFile */ /* existsFile */ /* fileExt */ /* fileName */ /* filePath */ /* closeFile */ /* */ /* avec 2 paramètres : */ /* */ /* copyFile */ /* moveFile */ /* say2 */ /* */ /* avec 3 paramètres : */ /* */ /* appendFile */ /* */ /******************************************************************************/ /* */ /* Exemples d'utilisation : (le caractère ^ sert de séparateur) */ /* */ /* call fileUtils("copyFile^test.a^test.b") */ /* */ /* rfu = fileUtils("copyFile^test.a^test.b") */ /* if rfu \=0 then say " Problème : " rfu */ /* */ /* */ /* */ /* */ /* */ /******************************************************************************/ /* */ /* Pour forcer le type du système d'exploitation, on peut utilisr la */ /* variable d'environnement OSTYPE. Par exemple : */ /* */ /* export OSTYPE=UNX (sous Linux sous bash, à mettre dans .bashrc) */ /* set OSTYPE=DOS (sous Dos/Windows, à mettre dans autoexec.bat) */ /* */ /******************************************************************************/ /* */ /* Pour que ce fichier soit accessible par tout script Rexx/Regina, il */ /* faut positionner la variable d'environnement REGINA_MACROS. */ /* Par exemple : */ /* */ /* export REGINA_MACROS=/usr/local/bin (sous Linux) */ /* set REGINA_MACROS=C:\Scripts (sous Dos/Windows) */ /* */ /******************************************************************************/ /* */ /* L'affichage des fichiers sous Dos se fait avec la commande list. (ext) */ /* L'affichage des fichiers sous Unx se fait avec la commande more. (int) */ /* Les fichiers fileUtils.test1 et fileUtils.test2 permettent de tester */ /* si ce fichier est correctement installé. */ /* */ /******************************************************************************/ parse arg largs dbg = 0 /* 1 for normal debug, 0 for normal operation, */ fic. = "" if dbg=1 then do say say " entering fileUtils ; requested : = " largs say end /* fin de si dbg=1 */ largs = largs"^" if dbg=1 then do say say " transformed largs = " largs end /* fin de si dbg=1 */ /* gestion des paramètres */ nf = -1 idc = index(largs,"^") do while idc > 0 nf = nf + 1 if nf = 0 then prog = substr(largs,1,idc-1) else fic.nf = substr(largs,1,idc-1) largs = substr(largs,idc+1) if dbg=1 then say " remaining args : " largs idc = index(largs,"^") end /* fin tant que idc > 0 */ if dbg=1 then say " prog " prog " fic1 =" fic.1 " fic2 =" fic.2 " fic3 =" fic.3 call checkOs resFu = 0 /* gestion des fonctions qui demandent une variable en retour dans le stack */ select /* fonctions qui affichent à l'écran ou qui attendent au clavier */ when prog = "clrScr" then call clrScr when prog = "seeFile" then call seeFile fic.1 when prog = "attends" then call attends /* fonctions qui envoient une variable en retour dans le stack */ when prog = "cpy" then call cpy when prog = "cpyWeb" then call cpyWeb when prog = "osName" then call osName when prog = "uName" then call uName when prog = "currentDir" then call currentDir when prog = "versionFu" then call versionFu when prog = "baseName" then call baseName fic.1 when prog = "fileExt" then call fileExt fic.1 when prog = "fileName" then call fileName fic.1 when prog = "filePath" then call filePath fic.1 when prog = "pathName" then call filePath fic.1 when prog = "checkFile" then call checkFile fic.1 when prog = "delFile" then call delFile fic.1 when prog = "deleteFile" then call delFile fic.1 when prog = "existsFile" then call existsFile fic.1 when prog = "closeFile" then call closeFile fic.1 when prog = "say2" then call say2 fic.1 fic.2 /* fonctions qui agissent sur les fichiers */ when prog = "copyFile" then call copyFile fic.1 fic.2 when prog = "moveFile" then call moveFile fic.1 fic.2 when prog = "appendFile" then call appendFile fic.1 fic.2 fic.3 otherwise do return " unkown file action'"||prog"' ; bad spelling ?" end /* fin de otherwise */ end /* fin de select sur prog */ return resFu /* fin de programme fileUtils */ /******************************************************************************/ /* procédure principale qui renvoie détecte le nom du systeme */ /* (elle gère aussi le nom des commandes à exécuter) */ checkOs: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg nomOs = "?" parse upper source mxv if index(mxv,"PERSONAL") > 0 then nomOS = "dos" if index(mxv,"SAA") > 0 then nomOs = "os2" if index(mxv,"LINUX") > 0 then nomOs = "unx" if index(mxv,"UNIX") > 0 then nomOs = "unx" if index(mxv,"WINDOWS") > 0 then nomOs = "dos" if nomOs = "?" then do osType = translate(value("OSTYPE",,"SYSTEM")) if index(translate(osType),"LINUX") > 0 then nomOs = "unx" ; if index(translate(osType),"DOS") > 0 then nomOs = "dos" ; end /* fin de si nomOs est "?" */ if osType = "?" then do say say " unknown Os ; exiting... " exit end /* fin de si nomOs est "?" */ if dbg=1 then say " nomOs = " nomOs if (nomOs="dos") | (nomOs="os2") then do viewFile = " list" mvFile = " move" kpy1File = " copy" kpy2File = " > nul" del1File = " if exist " del2File = " del " del3File = " > nul " efface = " cls" end /* fin de si nomOs est "dos" */ else if (nomOs="hpux") | (nomOs="unx") then do viewFile = " more" mvFile = " mv" kpy1File = " cp" kpy2File = " 2>/dev/null" del1File = " if test -r " del2File = " ; then rm " del3File = " 2>/dev/null ; fi ; " efface = " clear " end /* fin de si nomOs est "unx" ou "hpux" */ if dbg=1 then say " osName is : " nomOs return 0 /* fin de fonction checkOs */ /******************************************************************************/ /* procédure qui renvoie le nom du systeme sur 3 lettres */ osName: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu if dbg=1 then say " Os is : " nomOs resFu = nomOs return 0 /* fin de fonction osName */ /* procédure qui dit de quel unix il s'agit */ uName: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu if dbg=1 then say " Os is : " nomOs ftmp = "/tmp/uname.txt" cmd = "uname -a > " ftmp cmd ltmp = linein(ftmp) if dbg=1 then say ltmp "rm -rf" ftmp nomUnix = word(ltmp,2) resFu = nomUnix return 0 /* fin de fonction osName */ /******************************************************************************/ /* procédure qui renvoie la version de fileUtils */ versionFu: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu if dbg=1 then say " Os is : " nomOs txt = word(sourceline(6),4) word(sourceline(6),5) resFu =txt return 0 /* fin de fonction versionFu */ /******************************************************************************/ /* procédure qui détruit un fichier */ delFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg dfic if dbg=1 then say " deleting file : " dfic cmd = del1File dfic del2File dfic del3File if dbg=1 then say " commande : " cmd cmd return 0 /* fin de fonction delFile */ /******************************************************************************/ /* procédure qui ferme un fichier */ closeFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg dfic if dbg=1 then say " closing file : " dfic call lineout dfic rf = stream(dfic,'command','close') return 0 /* fin de fonction delFile */ /******************************************************************************/ /* procédure qui visualise le contenu d'un fichier */ seeFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg sfic ; call checkFile sfic ; viewFile sfic return 0 /* fin de fonction seeFile */ /******************************************************************************/ /* procédure qui dit si un fichier existe */ existsFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu parse arg darg f_arg = word(darg,1) if dbg=1 then say " existence of file '"f_arg"'" if lines(f_arg)>0 then ret = 1 else ret = 0 if dbg=1 then say " returned : " ret resFu = ret return 0 /* fin de fonction existsFile */ /******************************************************************************/ /* procédure qui teste si un fichier existe */ checkFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg ckfic ; signal on notready ll = linein( ckfic) ; call lineout ckfic rf = stream(ckfic,'command','close') return 0 /* fin de fonction checkFile */ /******************************************************************************/ /* procédure qui copie un fichier */ copyFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg cfic1 cfic2 . call checkFile cfic1 if cfic2="" then say " . Il manque un nom de fichier (au moins) dans la commande copyFile " else kpy1File cfic1 cfic2 kpy2File return 0 /* fin de fonction copyFile */ /******************************************************************************/ /* procédure qui déplace un fichier */ moveFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg cfic1 cfic2 . call checkFile cfic1 if cfic2="" then say " . Il manque un nom de fichier (au moins) dans la commande copyFile " else mvFile cfic1 cfic2 return 0 /* fin de fonction moveFile */ /******************************************************************************/ /* procédure qui concaténe deux fichiers */ appendFile: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg parse arg fe1 fe2 fsor ftmp = "ftmp.tmp" call checkFile fe1 call checkFile fe2 do while lines(fe1) > 0 ll = linein(fe1) call lineout ftmp , ll end /* fin tant que sur fe1 */ do while lines(fe2) > 0 ll = linein(fe2) call lineout ftmp , ll end /* fin tant que sur fe2 */ call lineout fe1 rf = stream(fe1,'command','close') call lineout fe2 rf = stream(fe2,'command','close') call lineout ftmp rf = stream(ftmp,'command','close') call copyFile ftmp fsor call delFile ftmp return 0 /* fin de fonction appendFile */ /******************************************************************************/ /* procédure qui efface l'écran */ clrScr: procedure efface return 0 /* fin de fonction clrScr */ /******************************************************************************/ /* procédure qui gère la présence d'un fichier */ notready: file =condition('D') say " -- ! -- 'Fichier' " file " 'non vu dans le cd courant !' " resFu = -1 exit -1 /* fin de fonction notready */ /******************************************************************************/ /* procédure qui renvoie le nom de base (fn et ext) d'un fichier */ baseName: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu parse arg fid if dbg=1 then say " baseName de " fid sbn = "" if nomOs= "dos" then charsep = "\" else charsep = "/" if dbg=1 then say " nomOs = " nomOS " charsep = " charsep dps = lastpos(charsep,fid) if dps=0 then sbn = fid else sbn = substr(fid,dps+1,length(fid)-dps) if dbg=1 then say " returned : " sbn resFu = sbn return 0 /* fin de fonction baseName */ /******************************************************************************/ /* procédure qui renvoie l'extension d'un fichier */ fileExt: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu parse arg fid if dbg=1 then say " fileExt de " fid sbn = "" dps = lastpos(".",fid) if dps=0 then sbn = "" else sbn = substr(fid,dps+1,length(fid)-dps) if dbg=1 then say " returned : " sbn resFu = sbn return 0 /* fin de fonction fileExt */ /* procédure qui renvoie le nomseul d'un fichier */ fileName: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu parse arg fid if dbg=1 then say " fileName de " fid fid = fileut("baseName^"fid) sbn = "" dps = lastpos(".",fid) if dps=0 then sbn = fid else sbn = substr(fid,1,dps-1) if dbg=1 then say " returned : " sbn resFu = sbn return 0 /* fin de fonction fileExt */ /******************************************************************************/ /* procédure qui renvoie le chemin d'accès du fichier */ filePath: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu parse arg fid if dbg=1 then say " pathname de " fid spn = "" if nomOs= "dos" then charsep = "\" else charsep = "/" dps = lastpos(charsep,fid) if dps=0 then spn = " " else spn = substr(fid,1,dps-1) if dbg=1 then say " returned : <"spn">" resFu = spn return 0 /* fin de fonction filePath */ /******************************************************************************/ /* procédure qui renvoie le chemin d'accès courant */ currentDir: procedure expose nomOs del1File del2File del3File viewFile mvFile kpy1File kpy2File efface dbg resFu if nomOs = "unx" then 'pwd | rxqueue' else 'cd | rxqueue' do while Queued() > 0 ; parse pull envLine ; end resFu = envLine return 0 /* fin de fonction currentDir */ /******************************************************************************/ /* procédure qui renvoie le chemin d'accès courant */ say2: procedure expose dbg parse arg nf lal if dbg=1 then say " say2 pour " nf " et " lal say lal call lineout nf , lal return 0 /* fin de fonction currentDir */ /******************************************************************************/ /* procédure de copyright simple */ cpy: procedure say say " Copyright 2000 - Gilles.HUNAULT@univ-angers.fr " say " http://www.info.univ-angers.fr/~gh/" say return 0 /* fin de fonction cpy */ /******************************************************************************/ /* procédure d'attente au clavier */ attends: call charout " ok ? " parse pull repUt if length(repUt)>0 then exit 0 return /******************************************************************************/ /* procédure de copyright pour le web */ cpyweb: procedure say '<font color="#OOOOOO"><p><p><pre><font size=3><p><hr><p>' say " Copyright 2000 - Gilles.HUNAULT@univ-angers.fr " say " http://www.info.univ-angers.fr/~gh/" say "</PRE>" say "</BODY>" say "</HTML>" return 0 /* fin de fonction cpyweb */ /******* fin de fichier fileUtils.rex ****************************************/ /* faut-il implémenter nameNoExt dosUnit dosFileUnit uc lc ucfirst trim ltrim trim explode=split join iota sum psum avg pavg std pstd sqrt ln exp rpos(right) nword(negative) nsorta(numeric,array) asorta(alphabetic,array) nsorts(numeric,sentence) asorts(alphabetic,sentence) avalues(array) svalues(string) dir=ls selectSimpleMySql selectMultipleMySql wait progBar (barre de progression) noDblChar *//* (gH) -_- REXXUT.rex ; TimeStamp (unix) : 08 Décembre 2006 vers 11:02 */ /* */ /******************************************************************************/ /* */ /* */ /* */ /* Fichier : REXXUT.rex v-2.6 */ /* */ /* */ /* Gilles.HUNAULT@univ-angers.fr */ /* http://www.info.univ-angers.fr/~gh/ */ /* */ /* */ /* " Sous-programmes rex d'intérêt général " */ /* */ /* */ /******************************************************************************/ /* */ /* Liste des fonctions disponibles : */ /* (attention aux majuscules ! sAy2 est incorrect à cause du A) */ /* */ /* sans paramètres : */ /* */ /* versionRu */ /* dateHeure */ /* */ /* avec 1 paramètre : */ /* */ /* triPhrase */ /* asg (qui renvoie nbl, moy, var, ect et cdv) */ /* */ /* avec 2 paramètres : */ /* */ /* formatZero */ /* racine */ /* surncard */ /* surncarg */ /* say2 écrit à l'écran et dans un fichier */ /* cor renvoie le coefficient de corrélation linéaire */ /* getcol récupère une colonne d'un fichier */ /* */ /******************************************************************************/ /* */ /* Exemples d'utilisation : (le caractère ^ sert de séparateur) */ /* */ /* r = rexxut("racine^"n) */ /* */ /******************************************************************************/ /* */ /* Pour forcer le type du système d'exploitation, on peut utiliser la */ /* variable d'environnement OSTYPE. Par exemple : */ /* */ /* export OSTYPE=UNX (sous Linux sous bash, à mettre dans .bashrc) */ /* set OSTYPE=DOS (sous Dos/Windows, à mettre dans autoexec.bat) */ /* */ /******************************************************************************/ /* */ /* Pour que ce fichier soit accessible par tout script Rexx/Regina, il */ /* faut positionner la variable d'environnement REGINA_MACROS. */ /* Par exemple : */ /* */ /* export REGINA_MACROS=/usr/local/bin (sous Linux) */ /* set REGINA_MACROS=C:\Scripts (sous Dos/Windows) */ /* */ /******************************************************************************/ /* trim ltrim rtrim via strip b l t */ parse arg largs dbg = 0 /* 1 for normal debug, 0 for normal operation, */ rxu. = "" if dbg=1 then do say say " entering REXXUT ; requested : = " largs say end /* fin de si dbg=1 */ largs = largs"^" if dbg=1 then do say say " transformed largs = " largs end /* fin de si dbg=1 */ /* gestion des paramètres */ nf = -1 idc = index(largs,"^") do while idc > 0 nf = nf + 1 if nf = 0 then prog = substr(largs,1,idc-1) else rxu.nf = substr(largs,1,idc-1) largs = substr(largs,idc+1) if dbg=1 then say " remaining args : " largs idc = index(largs,"^") end /* fin tant que idc > 0 */ if dbg=1 then say " prog " prog " rxu1 =" rxu.1 " rxu2 =" rxu.2 " rxu3 =" rxu.3 resRu = " ??? ??? -- ???? --- ??? " /* gestion des fonctions qui demandent une variable en retour dans le stack */ select when prog = "asg" then call asg rxu.1 when prog = "dateHeure" then call dateHeure when prog = "formatZero" then call formatZero rxu.1 rxu.2 when prog = "getcol" then call getcol rxu.1 rxu.2 when prog = "racine" then call racine rxu.1 when prog = "say2" then call say2 rxu.1 rxu.2 when prog = "surncard" then call surncard rxu.1 rxu.2 when prog = "surncarg" then call surncarg rxu.1 rxu.2 when prog = "triPhrase" then call triphrase rxu.1 when prog = "versionRu" then call versionRu when prog = "minu" then call minu rxu.1 otherwise do return " unkown file action'"||prog"' ; bad spelling ?" end /* fin de otherwise */ end /* fin de select sur prog */ return resRu /* fin de programme rexxut */ /******************************************************************************/ /******************************************************************************/ /* procédure qui ajoute des 0 à gauche de numer pour faire longr caractères */ formatZero: procedure expose dbg resRu parse arg numer longr chFmt = numer do while length(chFmt) < longr chFmt = "0"||chFmt end /* fin tant que */ resRu = chFmt return 0 /******************************************************************************/ /* procédure qui traduit en minuscule */ minu: procedure expose dbg resRu parse arg chenEnt chenSor = translate(chenEnt,"abcdefghijklmnopqrstuvwxyzee","ABCDEFGHIJKLMNOPQRSTUVWXYZÉË") resRu = chenSor return 0 /******************************************************************************/ /* procédure qui calcule la racine carrée */ racine: procedure expose dbg resRu numeric digits 15 arg x if dbg=1 then say " on veut la racine de " x if x> 1 then rr = 1 else rr = 0.9 do i = 1 to 20 rr = (x/(2*rr)) + rr/2 end /* fin pour */ resRu = rr return 0 /******************************************************************************/ /* procédure qui calcule les statistiques élémentaires */ asg: procedure expose dbg resRu numeric digits 15 arg x if dbg=1 then say " on veut les stat de " x n = words(x) if n = 0 then do moy = 0 var = 0 ect = 0 cdv = -1 end ; else do som = 0 /* somme des valeurs */ sdc = 0 /* somme des carrés */ do i = 1 to n vc = word(x,i) som = som + vc sdc = sdc + vc*vc end /* fin pour */ moy = som / n var = (sdc/n) - moy*moy ect = rexxut("racine^"var) if moy=0 then cdv = -1 else cdv = 100.0*ect/moy end /* fin si */ resRu = n moy var ect cdv return 0 /******************************************************************************/ /* procédure qui écrit dans le fichier et à l'écran */ say2: procedure expose dbg resRu parse arg nf lal if dbg=1 then say " say2 pour " nf " et " lal say lal call lineout nf , lal return 0 /******************************************************************************/ /* procédure qui cadre à gauche sur long la variable chen */ surncarg: procedure expose dbg resRu parse arg long chen if dbg=1 then say " surncarg cadrage sur " long " de " chen do while length(chen)<long chen = chen||" " end /* fin tant que */ if dbg=1 then say " on renvoie " chen resRu = chen return 0 /******************************************************************************/ /* procédure qui cadre à droite sur long la variable chen */ surncard: procedure expose dbg resRu parse arg long chen if dbg=1 then say " surncarg cadrage sur " long " de " chen do while length(chen)<long chen = " "||chen end /* fin tant que */ if dbg=1 then say " on renvoie " chen resRu = chen return 0 /******************************************************************************/ /* procédure qui récupère la colonne numc du fichier fn */ getcol: procedure expose dbg resRu parse arg fn numc if dbg=1 then say " getcol fichier " fn " colonne " numc lacol = "" do while lines(fn)>0 lig = linein(fn) lacol = lacol word(lig,numc) end /* fin tant que */ if dbg=1 then say " on renvoie " lacol rf = fileut("closeFile^"fn) resRu = lacol return 0 /******************************************************************************/ /* procédure qui renvoie trie une phrase par ordre numérique de ses mots */ triPhrase: procedure expose resRu parse arg lis /* conversion en tableau */ nt. = "" ; do i = 1 to words(lis) ; nt.i = word(lis,i) ; end /* tri du tableau */ do i = 1 to words(lis) do j = i+1 to words(lis) if nt.i > nt.j then do etmp = nt.i nt.i = nt.j nt.j = etmp end /* fin de si */ end /* fin pour j */ end /* fin pour i */ /* reconversion en phrase */ nlis = "" ; do i = 1 to words(lis) ; nlis = nlis nt.i ; end resRu = nlis return 0 /******************************************************************************/ /* procédure qui renvoie la version de rexxut */ versionRu: procedure expose resRu if dbg=1 then say " Os is : " fileut("osName") resRu = word(sourceline(6),4) word(sourceline(6),5) return 0 /* fin de fonction versionFu */ /******************************************************************************/ /* procédure qui renvoie la date et l'heure */ dateHeure: procedure expose resRu if dbg=1 then say " Os is : " fileut("osName") resRu = date() || " vers " || time() return 0 /* fin de fonction versionFu */ /******************************************************************************/ /******* fin de fichier rexxut.rex ****************************************/ /* faut-il implémenter dosUnit dosFileUnit ucfirst explode=split join iota sum psum avg pavg std pstd ln exp rpos(right) nword(negative) lastword nsorta(numeric,array) asorta(alphabetic,array) nsorts(numeric,sentence) asorts(alphabetic,sentence) avalues(array) svalues(string) dir=ls selectSimpleMySql selectMultipleMySql wait progBar (barre de progression) noDblChar cadreTexte: parse arg long , chen return substr(chen copies(" ",long) , 1 , long ) */
Code-source php de cette page ; code javascript utilisé. Retour à la page principale du cours.
Retour à la page principale de (gH)