Langages Interprétés

Définition

Les langages interprétés sont, par définition, des langages compris par au moins un interpréteur (certains langages pouvant être interprétés ou compilés, au choix, d'autres, comme Forth, ayant un statut moins clair mélangeant interprétation et compilation).

Quelques langages interprétés

Voici une liste (non exhaustive) de langages pour lesquels il existe au moins un interpréteur:

Travaux pratiques

Sujet

En tant que nouvel embauché corvéable à merci, on vous a demandé de repérer les alias mails (disponibles en faisant ypcat -k aliases) qui pointent (peut-être indirectement) sur une adresse du type xyz@inf, et dont le compte associé (ici xyz) n'existe plus (absent des comptes disponibles lorsque l'on fait ypcat passwd). De plus, on vous demande pour chaque compte de faire la liste des alias disponibles correspondant exactement à ce compte, et la liste des alias englobant ce compte. Pour des raisons de présentation, on vous demande de pouvoir afficher également le prénom et le nom du propriétaire du compte. Vous ne connaissez pas exactement le format des fichiers concernés. Plutôt que d'utiliser un langage que vous connaissez (C, Ada, ...) qui peut ne pas être adapté, vous décidez d'utiliser un langage interprété. Ruby est conseillé pour le TP, les autres langages sont autorisés.

Ruby

Introduction

Le langage Ruby est un langage interprété en pleine évolution, où tout est objet. Le site principal de Ruby contient des liens vers les différentes versions et les bibliothèques du langage. Le guide utilisateur Ruby en français est disponible (merci à Alain Feler).

Particularités

Ruby a certaines particularités par rapport à d'autres langages plus classiques:

Apprendre Ruby

Le guide de référence de Ruby est en fait un tutoriel, qui va nous servir tout au long de cette séance de travaux pratiques.

But du TP: suivre le tutoriel pas à pas aussi loin que nécessaire et maîtriser suffisamment un langage interprété (Ruby) à la fin de la période de façon à remplir la mission demandée. C'est possible (et amusant)!

Il est possible (sans assistance) de choisir un autre langage interprété (Perl, Python, ...).

Exemples

Ces exemples ne sont à utiliser que comme aide, une fois que vous aurez lu le tutoriel.

Quitte à recopier le texte indiqué ici, autant récupérer directement le fichier d'exemple en cliquant ici.

Entête du fichier Ruby

#! /usr/local/bin/ruby
# -*- ruby -*-

Extraire les alias


#
# Retourne un tableau associatif (hash) qui
# associe à un alias la liste des destinataires.
#
def aliases
  # a est un tableau associatif vide au départ
  a = {}
  # fd est un descripteur représentant le résultat de
  # la commande ypcat -k aliases (ouvert en lecture)
  fd = open ("|ypcat -k aliases", "r")
  # Pour chaque ligne, que l'on appelle localement l
  fd.each_line {|l|
    # Enlever le caractère \n de fin de ligne
    l.chomp!
    # Repérer l'expression alias: nom1, nom2, nom3
    l =~ /^(\S+)\s(.*)$/
    # Renseigner le tableau associatif avec
    #  a['alias'] = ['nom1', 'nom2', 'nom3']
    a[$1] = $2.split /,\s*/
  }
  # On ferme le descripteur
  fd.close
  # On retourne le tableau
  return a
end

#
# Exemple:
#
#  a = aliases
#  a ["postmaster"]
#         => ["dax", "beyssac", "tardieu"]
#

Trouver les comptes correspondant à un alias


# Entrée: l'alias à rechercher et le tableau associatif des alias
# Sortie: la liste des comptes qualifiés dans lesquels se trouve ce compte

def cherche_aliases nom, al
  if al.key? nom then
    # Ce nom est présent dans les alias, le résoudre et aplatir
    # la liste (flatten). Mais d'abord, retirer le nom lui-même
    # de la liste.
    dests = al[nom]
    dests.delete nom
    (dests.map {|a| cherche_aliases a, al}).flatten
  else
    [nom]
  end
end

#
# Exemple:
#
#  a = aliases
#  cherche_aliases "postmaster", a
#           => ["dax@inf", "beyssac@bofh", "tardieu@inf"]
#

Liste des alias associés à un compte


# Entrée: le tableau associatif des alias
# Sortie: le tableau associant à chaque compte qualifié les alias
#         auxquels il appartient
def list_aliases aliases
  # Tableau associatif de résultats, initialement vide
  r = {}
  # Pour chaque alias appelé localement a
  aliases.keys.each {|a|
    # Pour chaque compte appelé localement c associé à cet alias
    (cherche_aliases a, aliases).each {|c|
      # Si ce compte existe dans le tableau résultat, rajouter
      # l'alias, sinon créer la liste initiale (à un élément pour l'instant)
      if r.key? c then
        r[c] << a
      else
        r[c] = [a]
      end
    }
  }
  return r
end

#
# Exemple:
#
#  a = aliases
#  r = list_aliases a
#  r['peyrade@dir']
#         => ["marc.peyrade", "enst.fr-administrative-contact", "peyrade"]
#

Extraire les comptes


#
# Retourne un tableau associatif contenant les comptes présents dans
# la commande ypcat passwd et les prénom/nom associés (sous forme
# d'une chaîne unique).
#
def accounts
  # Tableau associatif vide initialement
  c = {}
  # fd est un descripteur représentant le résultat de
  # la commande ypcat passwd (ouvert en lecture)
  fd = open ("|ypcat passwd", "r")
  # Pour chaque ligne, que l'on appelle localement l
  fd.each_line {|l|
    # Repérer nom:XXX:XXX:XXX:Prénom Nom etc.:...
    l =~ /^([^:]+):[^:]*:[^:]*:[^:]*:([^:]*):/
    # Enregister le prénom et le nom, en enlevant ce qu'il peut y
    # avoir après la virgule
    c[$1] = ($2.split ',')[0]
  }
  # On ferme le descripteur
  fd.close
  # On retourne le tableau associatif
  return c
end

#
# Exemple:
#
#  c = accounts
#  c['tardieu']
#         => "Samuel Tardieu"
#

Samuel Tardieu
Last modified: Tue Feb 12 15:10:13 CET 2002