Objectifs et évaluation

Objectifs

Ces deux séances de TD Regexp visent à
  • vous familiariser avec la syntaxe des expressions régulières (ou expressions rationnelles).
  • montrer des cas d'utilisation pratiques, utilisant les outils unix classiques.

Évaluation

Cet enseignement est une simple introduction rapide, qui compte pour epsilon dans l'UF. L'évaluation se veut très pragmatique :

  • La présence aux deux TDs, en étant actif et de bonne humeur, vous octroie une note de 10 pour cette matière (à multiplier par un coefficient très faible dans l'UF).
  • Après les TDs, un examen rapide sur machine sera organisé. Votre présence est facultative si vous étiez présents aux deux TDs (vous aurez alors 10 par défaut).
  • L'examen permet d'obtenir une note entre 0 et 20. Il n'est pas spécialement facile (les années précédentes, la moyenne tourne autour de 8). Quoi qu'il en soit, la note finale retenue sera au moins 10 si vous étiez bien présents aux TDs.

Indispensables pré-requis UNIX

Vous devez être familier avec :

Ces commandes shell :

  • mv (move, rename)
  • cp (copy)
  • rm (remove)
  • cd (change directory)
  • Rappel : ~/ désigne le homedir (répertoire personnel).

Ces commandes de base :

  • man commande (manuel d'une commande)
  • cat filename (afficher un fichier)
  • wc filename ou en lisant depuis stdin : wc (compter les caractères et les lignes)
  • uniq (supprime les lignes doublons qui se suivent)
  • sort (trier)

Ces combinateurs :

  • commande1 | commande2 (pipe)
  • commande > fichier (redirection)
  • pour les curieux : commande1 <(commande2)
    (assez méconnu) <(commande2) est un virtual file contenant la sortie de commande2

Les règles d'échappement :

  • Dans une commande unix, un argument peut être encapsulé dans des "guillemets" (double quotes) ou dans des 'apostrophes' (single quotes).
  • Bien sûr, si une guillemet ou une apostrophe se trouve à l'intérieur de l'argument, il faut un symbole d'échappement, le \ :
    • "exemple de guillemet \" à l'intérieur de guillemets"
    • 'exemple d\'apostrophe à l\'intérieur d'apostrophes'
  • Un argument avec espace(s) doit être encapsulé : "un seul argument".
Enfin, vous pouvez utiliser cet outil qui analyse les commandes shell.

Étape 1 : trace réseau

Les deux membres du binôme doivent s'exercer.
Changez les rôles régulièrement !

Préparation physique

  • Allez dans /mnt/commetud/3eme Annee MIC/Regexps.
  • Copiez chez vous les fichiers sur lesquels nous allons travailler : extrait_trace, villes.txt et page_microsoft.html
  • Ouvrez votre fichier extrait_trace avec un éditeur quelconque, par exemple Pluma. Notez quelque part combien de lignes contient ce fichier.
  • Repérez visuellement pour chaque paquet réseau les IP source et destination, ainsi que les ports source et destination (1215 et 80 par exemple)

Préparation mentale

  • Dans un premier temps, nous souhaitons examiner uniquement les paquets relatifs au protocole FTP (ports 21 et 22).
  • Commençons par la tentative naïve : faire une recherche simple sans regexp avec CTRL+F (ou menu RECHERCHER) et taper 21.
    Cliquez sur la flèche pour passer à l'occurrence suivante.
  • La recherche vous montre tous les "21" contenus dans le fichier. Il y en a beaucoup trop.
  • Astucieux comme vous êtes, recommencez en cherchant " 21 " (avec un espace devant et après). Pas de chance, il y en a encore trop.
  • Êtes-vous convaincus qu'une recherche simple ne peut pas marcher ? Si vous n'êtes pas convaincus, manifestez-vous.
  • Nous allons donc affiner la recherche en utilisant des regexps. Quittez pluma, nous allons maintenant travailler depuis un terminal.

grep 1 (la partie où l'on ne peut pas se tromper)

  • Ouvrez un terminal et placez-vous dans le bon répertoire.
  • Combien de lignes contient extrait_trace ? wc extrait_trace
  • Extraire les lignes qui contiennent 21 : grep 21 extrait_trace. Trouvez un moyen de les compter, il y en a 2197.
  • Pour avoir de la couleur, il suffit d'ajouter l'option --color=auto. Pour éviter de l'écrire à chaque fois, utiliser : alias grep="grep --color=auto".
    Ré-essayez grep 21 extrait_trace
  • Extraire les lignes qui contiennent 21 entre deux espaces : grep " 21 " extrait_trace (il y en a 754)
  • En lisant le manuel (man grep), trouvez la signification et testez (séparément) les options suivantes :
    • -i (forcément pas très utile avec 21)
    • -o (on passe de 754 à 809, pourquoi ?)
    • -v (on passe de 754 à 11338, c'est logique.)
    • -n (il y a de la couleur, c'est sympa)
    • -A 1 (et trouvez aussi l'option qui permet d'attraper les lignes situées avant)
  • Si vous avez bien travaillé, vous avez désormais le droit de consulter la version en ligne du manuel : //manpages.ubuntu.com/manpages/bionic/fr/man1/grep.1.html

grep 2 (la partie où l'on peut se tromper)

  • Utilisez maintenant les regexp dans grep : grep -E "[0-9]+" extrait_trace (qui est équivalent à egrep "[0-9]+" extrait_trace si vous utilisez egrep, pensez à définir l'alias avec alias egrep="egrep --color=auto")
    Exclamez-vous : "Sapristi !" (ou toute autre expression équivalente dans votre langage propre).
    Pour arrêter un défilement interminable, il faut tuer la commande : CTRL+C
  • Écrivez une regexp permettant de trouver toutes les adresses IP. Pour éviter de répéter trois fois la même regexp R, une notation spéciale existe (R){n} qui répète R exactement n fois, ou encore (R){2,5} (par exemple) qui répète R au moins 2 fois et au plus 5 fois.
    Si besoin, vous pouvez utiliser l'outil en ligne //regex101.com/ pour concevoir votre regexp.
    Questions de compréhension :
    • Pourquoi la regexp [21] ne correspond pas au nombre 21 ? À quoi correspond [22] ?
    • Pourquoi la regexp [0-255] ne correspond pas du tout aux nombres entre 0 et 255 ?
    • Comment faire pour repérer un nombre entre 0 et 999 ? (c'est plus simple que repérer un nombre entre 0 et 255)
    • Enfin, pour simplifier encore, comment repérer un nombre tout court ?
  • Reprenez maintenant votre recherche de paquets FTP en essayant d'avoir la regexp la plus simple possible qui trouve tous les paquets concernant les ports 21 ou 22 (j'en trouve 1792 — si vous en trouvez 1840, cherchez "2262" dans la sortie de votre commande grep pour trouver l'erreur).
  • Voici un pratique catalogue de ce que l'on peut faire avec grep : tutorial grep

grep | sort | uniq

  • Pour obtenir tous les nombres présents dans le fichier : egrep -o "[0-9]+" extrait_trace
  • On veut la même chose, mais sans les doublons (vous pouvez être content si vous en trouvez 4183 distincts). Si vous ne savez pas comment faire, relisez le titre.
  • Essayez avec l'option sort -n et observez que les nombres sont bien triés cette fois.
  • Maintenant que vous avez tout compris, extrayez toutes les adresses MAC (distinctes) du fichier. J'en trouve 3.
  • Extrayez aussi toutes les adresses IP. J'en trouve 6.

Interlude

Petite pause : allez lire cette page. (Cette page seulement !)

La réécriture, avec sed (jusqu'ici, c'était facile)

  • Dans toute cette partie, vous pouvez utiliser man sed pour vous documenter ou lire ce tutoriel : grymoire.
  • Pour découvrir sed, tapez cette commande : sed -r "s/[0-9]+/TCHA/g" extrait_trace
    • Cette commande remplace (s = substitute) tous les nombres par "TCHA". Les / servent de délimiteur.
    • Le g à la fin de la commande sed est l'option "global" (sinon sed ne remplace que le premier nombre trouvé sur chaque ligne.
  • Remplacez toutes les adresses MAC par le mot 'ICI-MAC'.
  • Nous voulons maintenant remplacer les adresses MAC, par exemple 00:04:75:f4:41:f5 par la même adresse entre parenthèse et précédée du mot 'MAC' : MAC(00:04:75:f4:41:f5).
    • Pour mémoriser un morceau de regexp, le mettre entre parenthèses.
    • Pour recopier le morceau mémorisé dans le motif de remplacement, utiliser \1(ou \2, \3 pour les deuxièmes, troisièmes parenthèses, voir le manuel pour les détails).
    • Par exemple, REMPLACER FOO([0-9]*)BAR par MOO\1 remplacera FOO125BAR par MOO125
    La dernière ligne du fichier devrait apparaître comme ceci :
    12:05:39.549333 MACADR(00:04:75:f4:41:f5) > MACADR(00:04:75:f4:35:c4), ethertype ...
  • Ré-écrivez l'heure du début de chaque ligne (e.g. 12:05:39.549333) avec cette notation : 12H05'39
    Vérifiez que la dernière ligne commence bien par
    12H05'39 00:04:75:f4:41:f5 ...
    Attention, les parenthèses sont numérotées de gauche à droite. La notation \3 désigne le contenu de la troisième parenthèse ouverte de votre regexp.
  • Trouvez un moyen (simple) de combiner les deux opérations précédentes pour obtenir
    12H05'39 MACADR(00:04:75:f4:41:f5) > MACADR(00:04:75:f4:35:c4), ethertype ...

Étape 2 : du XML et du pas XML

Du HTML chez Microsoft (XML)

Nous travaillons sur le fichier page_microsoft.html qui fut un temps la page d'accueil du site microsoft.fr

Ne cherchez pas à décrire précisément comment est construite une URL.
  • Listez toutes les URL qui commencent par http. Utilisez une regexp la plus simple possible
    Vous pourriez obtenir 180 URLs, dont voici les dernières : (méfiez-vous de http-equiv qui n'est pas une URL)
    https://www.linkedin.com/company/microsoft-france
    http://c.s-microsoft.com/fr-fr/CMSImages/LinkedIn_64x64.png?version=edebfe2b-f59f-4540-70fc-d47874b7b605
    https://www.youtube.com/channel/UC6mM0LIENRUTQ5yhs1v4xmg
    http://c.s-microsoft.com/fr-fr/CMSImages/YouTube_64x64.png?version=07b4cb3b-4e0b-8cff-4e86-bfe28ea4a484
    http://windows.microsoft.com/fr-fr/windows/home?WT.mc_id=MSCOM_FR_HP_FOOTERLEFT_Windows
    http://c.s-microsoft.com/fr-fr/CMSImages/windows_symbol.png?version=f1f9db81-67ef-8866-1be3-d5b1c1bb0b26
    http://products.office.com/fr-fr/?WT.mc_id=OAN_fr-fr_MSCOM-Footer-ProductSite-Office
    http://c.s-microsoft.com/fr-fr/CMSImages/office_symbol.png?version=8a3d8983-7b8
    http://c.s-microsoft.com/fr-fr/CMSScripts/script.jsx?k=26000e5d-5133-4171-5cbb-4622f4f7398d_f3c4a4eb-d525-0def-8753-f4835e2f9949_8c693876-7ed8-69ec-3e44-be17b34be6b9_93007181-29a3-a626-49b7-12b98955254f_4200337d-a1fd-0b86-7ace-60bb19a65c23_041f54d5-9d4c-1b87-9e7f-44db8acfcaa6_51077a6c-8fc6-7acc-1b57-af19d92ec422_193518ce-0483-747b-0dcd-e9e69355aee6
    http://c.microsoft.com/trans_pixel.aspx
  • Comptez combien vous obtenez d'URLs différentes. J'en trouve 167.
  • Listez les noms de serveurs différents trouvés dans ces URL (par exemple www.microsoft.com/). J'en trouve 39.
  • Cherchez les balises image <img et listez l'URL de ces images (située dans l'attribut src). J'en trouve 7. Constatez que l'une des images office_symbol.png est mal délimitée.
    src="http://c.s-microsoft.com/fr-fr/CMSImages/HPFeb15_social_Facebook.png?version=0acf48ba-289e-458e-d3da-f354d2e22824"
    src="http://c.s-microsoft.com/fr-fr/CMSImages/HPFeb15_social_Twitter.png?version=66009b38-f580-f4c7-1212-a77769a0bae0"
    src="http://c.s-microsoft.com/fr-fr/CMSImages/LinkedIn_64x64.png?version=edebfe2b-f59f-4540-70fc-d47874b7b605"
    src="http://c.s-microsoft.com/fr-fr/CMSImages/YouTube_64x64.png?version=07b4cb3b-4e0b-8cff-4e86-bfe28ea4a484"
    src="http://c.s-microsoft.com/fr-fr/CMSImages/windows_symbol.png?version=f1f9db81-67ef-8866-1be3-d5b1c1bb0b26"
    src="http://c.s-microsoft.com/fr-fr/CMSImages/office_symbol.png?version=8a3d8983-7b8
    src="http://c.microsoft.com/trans_pixel.aspx"

Un fichier pseudo-structuré (clairement pas du XML)

  • Examinez le fichier villes.txt. Il contient la liste à peu près complète des communes de France, avec leur code postal, numéro de département, population, surface, coordonnées et altitude.
    • Trouvez dans le fichier (avec une commande unix) une commune que vous connaissez. (Les données de population datent un peu.)
    • Certaines villes ont plusieurs codes postaux (Paris, Toulouse).
    • Le département n'est pas forcément un numéro, e.g. Bastia.
  • Combien de communes dans le département 31 ? (il y en a 589).
  • Et combien dans le département 75 ?
  • Trouvez les communes contenant deux apostrophes (il y en a 9).
  • Trouvez les communes contenant une seule apostrophe (il y en a 828).
  • Avec sed, ré-écrivez le fichier sous la forme : ville code-postal (coordonnées)
    Ozan  01190 [4.91667,46.3833,205]
    Cormoranche-sur-Saône  01290 [4.83333,46.2333,211]
    Plagne  01130 [5.73333,46.1833,922]
    Tossiat  01250 [5.31667,46.1333,501]
    Pouillat  01250 [5.43333,46.3333,770]
    Torcieu  01230 [5.4,45.9167,782]
    Replonges  01620 [4.88333,46.3,207]
    Si vous en avez besoin, sachez que le symbole ^ (hors crochets) signifie le début de la ligne.
    Comment vérifier que toutes les lignes ont bien été ré-écrites ?

Ressources