Valid XHTML     Valid CSS2    

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

  8. REXX : que font ces programmes ?

  9. REXX : fichiers dictionnaires d'un texte

 

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 total
     

On 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 :  

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.23
     

Sur 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 END
     
     
     
     

Le 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 END
     
     
     
     

Encore 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 Mo
     

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 END
     
     

Il 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                                            3
     

Et 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                                         1
     

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 :  

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 :  

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 18
     

Pour 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 :  

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 fait
     

On pourra utiliser REXXUT et FILEUT.

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 " nomarchive
     

Exemple 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 :  

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  return
     

on 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
     Smalltalk
     

     Fichier 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
                                             Smalltalk
     

L'é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:24
     

Pour 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 :  

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 gH    Retour à la page principale de   (gH)