Source de l'image :
"}],[{"text":"On dispose d'un texte, c'est à dire pour Python d'une chaîne de caractères (string).
Par ailleurs, on propose un motif, qui est lui aussi une chaîne de caractères.
Le problème consiste à détecter la présence du motif dans le texte, et éventuellement de remplacer ce motif par un autre..
Nous avons des fonctions définies par python qui peuvent résoudre le problème:
str.find(sub[, start[, end]])
retourne le premier indice de la chaîne où la sous-chaîne sub est trouvée ; si start et end sont précisés, le domaine de recherche est la sous-chaîne formée des caractères dont l'indice est entre les valeurs de start et de end (la tranche commence avec start et se termine avant end). La méthode retourne -1 en cas d'échec de la recherche.
str.index(sub[, start[, end]])
comme find(), mais lève une exception ValueError si la sous-chaîne n'est pas trouvée.
Cela permet de programmer les ruptures de séquences avec des exceptions. str.rfind(sub[, start[, end]])
comme find(), mais commence par la fin de la chaîne.
str.rindex(sub[, start[, end]])
comme rfind() mais lève une exception ValueError si la sous-chaîne n'est pas trouvée.
str.count(sub[, start[, end]])
retourne le nombre d'occurrences de la sous-chaîne sub dans la tranche [start,end]
","title":"Trouver"},{"edit":"On a la chaine de caractère suivante :
texte = \"\"\"
Un IDE ou environnement de développement est un logiciel constitué d'outils qui facilitent l'écriture et les tests dans un ou plusieurs langages de programmation.\\n
Cet IDE comporte en général un éditeur avec coloration syntaxique,\\nun système de gestion de fichiers (sauvegarde/chargement),\\nun compilateur, un exécuteur de programme, un système d'aide en ligne,\\ndes indicateurs de syntaxe etc.
Le plus connu est peut être Éclipse.
\"\"\"
La première occurence du motif. La numérotation commence 0
motif = \"IDE\"
resultat = texte.find(motif)
print (\"première occurence du motif :\", resultat)
Le nombre d'occurrences du motif
resultat= texte.count (motif)
print (\"nombre d'occurrences du motif :\",resultat)
Rechercher un motif avec problème de casse (caractère en minuscule ou majuscule)
motif = \"éclipse\"
resultat = (texte.upper()).find(motif.upper())
print (motif, \"est présent comme\",texte[resultat:resultat+len(motif)])
Ecrire et tester le code ci-dessus.
Il existe une fonction pour remplacer un motif dans un texte:
str.replace(old, new[, count])
retourne une copie de la chaîne où toutes les occurrences de la sous-chaîne old sont remplacées par la chaîne new. Si la valeur count est précisée, seules les count premières occurrences sont remplacées.
Remplacer le motif \\n (Retour à la ligne) par un espace (\" \").
print (texte)
motif = \"\\n\"
resultat = texte.replace(motif, \" \")
print (resultat)
Ecrire et tester le code.
Mettre le résultat ci-dessous.
","title":"Exercice"},{"edit":" Ecrire les résultats ici.
"}],[{"text":"Avec python, nous pouvons découper une chaîne de texte. Pour cela, nous avons les fonctions suivantes:
str.split([sep[, maxsplit]])
retourne une liste de mots de la chaîne, en utilisant sep comme délimiteur. Si maxsplit est
donné, il y a au plus maxsplit coupures (et la liste a au plus maxsplit+1 éléments).
En l'absence de séparateur spécifié, ou avec le séparateur None, l'espace est considéré
comme séparateur.
str.splitlines([keepends])
retourne une liste des lignes de la chaîne. En principe, le séparateur de ligne n'est pas gardé, sauf si keepend est posé à True.
Ecrire les résultats ici.
"}],[{"text":"Découper une chaîne de caractère avec la fonction split:
texte = \"123,,456,\"
print(\"texte :\",texte)
# split
liste = texte.split (\",\")
print(\"liste :\", liste)
Découper une chaîne de caractère en liste à l'aide \\n (retour à la ligne).
texte = \"\\nABC\\nDEF\\nGHI\"
print (\"texte :\",texte)
liste = texte.splitlines()
print (\"liste :\", liste)
Découper une chaîne de caractère en liste à l'aide \\n et keepend
texte = \"\\nABC\\nDEF\\nGHI\"
print(\"texte :\",texte)
liste = texte.splitlines(True)
print(\"\\nliste :\", liste)
Tester les instructions et mettre le résultat ci-dessous.
","title":"Exercice"},{"edit":" Ecrire les résultats ici.
Les expressions régulières ou Regex (contraction de regular expression) est une manière commune de nommer les expressions régulières. Ces puissants outils permettent de représenter des spécimens de chaînes de caractères.
Les Regex sont employées pour examiner, changer et manier du texte comme nous l'avons réalisé précédemment.
On peut les voir dans des langages tels que Javascript, Python ou C
Pour utilser les expressions régulières en Python, il faut commencer par importer le module re :
import re # module des expressions régulières
Si nous reprenons le programme suivant qui permet de remplacer les \\n par un espace (\" \"):
texte = \"\"\"
Un IDE ou environnement de développement est un logiciel constitué d'outils qui facilitent l'écriture et les tests dans un ou plusieurs langages de programmation.\\n
Cet IDE comporte en général un éditeur avec coloration syntaxique,\\nun système de gestion de fichiers (sauvegarde/chargement),\\nun compilateur, un exécuteur de programme, un système d'aide en ligne,\\ndes indicateurs de syntaxe etc.
Le plus connu est peut être Éclipse.
\"\"\"
print(texte)
motif = \"\\n\"
resultat = texte.replace(motif, \" \")
print(resultat)
En utilisant, les expréssions régulières devient :
texte = \"\"\"
Un IDE ou environnement de développement est un logiciel constitué d'outils qui facilitent l'écriture et les tests dans un ou plusieurs langages de programmation.\\n
Cet IDE comporte en général un éditeur avec coloration syntaxique,\\nun système de gestion de fichiers (sauvegarde/chargement),\\nun compilateur, un exécuteur de programme, un système d'aide en ligne,\\ndes indicateurs de syntaxe etc.
Le plus connu est peut être Éclipse.
\"\"\"
motif = \"\\n\"
resultat = re.sub(\"\\n\", \" \", texte)
print(resultat)
Tester les 2 codes et conclure.
Ecrire ici vos résultats.
Pour la clarté du cours, nous traduirons lez verbes
to match par correspondre à,
et to search par rechercher.
Il ne faut pas chercher de signification \"intuitive\" à ces concepts qui ont un sens précis en Python.
On dispose d'un texte, c'est à dire pour Python une chaîne de caractères ; par ailleurs, on propose un patron (ou motif), qui est lui aussi une chaîne de caractères.
Le problème consiste à détecter une sous-chaîne respectant le patron dans le texte et éventuellement à remplacer par une chaîne prédéfinie la (ou les) sous-chaînes(s) trouvées.
D'autres opérations sont possibles, qui seront vues plus tard.
","title":"Poser le problème"},{"edit":" Ecrire ici le résultat.
La syntaxe pour compiler un patron est la suivante :
cpatron = re.compile(patron, directives)
Les directives se présentent sous forme d'un entier : chaque directive est une puissance de deux, et le paramètre directives est la somme de directives particulières.
Constante | Abrégé | Valeur | Signification |
IGNORECASE | I | 2 | ignorer la casse ; fonctionne avec les lettres accentuées |
LOCALE | L | 4 | définir comme \"lettre\" ce que la langue locale définit comme tel dans la variable système.; |
MULTILINE | M | 8 | considèrer le texte comme décomposé en lignes (le caractère \\n est le début de chaque ligne) |
DOTALL | S | 16 | considèrer le saut de ligne comme un caractère ordinaire. |
UNICODE | U | 32 | obsolète dans Python 3 |
VERBOSE | X | 64 | permettre d'écrire des commentaires dans les patrons. |
ASCII | A | 256 | permettre de travailler en ASCII |
On peut écrire indifféremment
re.IGNORECASE+re.MULTILINE ou re.I+re.M
Pour l'instant, nous travaillerons avec les directives IGNORECASE, MULTILINE et DOTALL.
On verra plus tard la directive VERBOSE.
La syntaxe des fonctions comparer et chercher est la suivante :
cpatron.search (texte)
cpatron.match (texte)
La recherche (search()) consiste à parcourir le texte depuis le début ; si le patron n'est pas identifiable dans le texte, la fonction retourne None. Sinon, elle retourne une instance de l'objet MatchObject, appartenant lui aussi au module _sre.
La comparaison (match()) consiste à identifier le début du texte au patron. Elle retourne None si aucune comparaison n'est possible. Sinon elle retourne une instance MatchObject.
L'objet : MatchObject
Cet objet peut être interrogé par ses méthodes. Pour l'instant, les méthodes start() (premier caractère reconnu) et stop() (position après le dernier caractère reconnu)
Nous importons la bibliothèque re et nous définissons la variable texte.
import re
texte = \"Un IDE ou \\\"environnement de développement\\\" est un logiciel \\
constitué d'outils qui facilitent l'écriture et les tests dans un \\
langage défini, voire plusieurs.\\
\\nCet IDE comporte en général un éditeur avec coloration syntaxique,\\
un système de gestion de fichiers (sauvegarde/chargement),\\
un compilateur, un exécuteur de programme, un système d'aide en ligne,\\
des indicateurs de syntaxe etc. \\
\\nLe plus connu est peut être Éclipse.\"
Pour rechercher un patron dans le texte, nous utilisons les instructions suivantes :
# recherche du patron dans le texte
patron = \"Cet IDE\"
cpatron = re.compile(patron)
resultat = cpatron.search(texte)
if resultat :
print (resultat.start(), resultat.end())
else:
print (resultat)
Pour la comparaison du patron au texte, nous utilisons les instructions suivantes
# comparaison du patron au texte
resultat = cpatron.match(texte)
if resultat :
print (resultat.start(), resultat.end())
else :
print (resultat)
Pour la comparaison du patron au texte, nous utiliserons les instructions suivantes:
# comparaison du patron au texte ; résultat affiché : None
resultat = cpatron.match(texte)
if resultat :
print (resultat.start(), resultat.end())
else :
print (resultat)
# comparaison du patron au texte ; résultat affiché : 0 6
patron = \"Un IDE\"
cpatron = re.compile (patron)
resultat = cpatron.match(texte)
if resultat :
print (resultat.start(), resultat.end())
else :
print (resultat)
Pour recherche en ignorant la casse, nous utiliserons les instructions suivantes:
# recherche en ignorant la casse
patron = \"éclipse\"
cpatron = re.compile (patron, re.IGNORECASE)
resultat = cpatron.search(texte)
if resultat :
print (resultat.start(), resultat.end())
else:
print (resultat)
Il existe plusieurs présentations syntaxiques pour les méthodes comme search(). Dans le script ci-dessus, search() est une méthode de l'objet SRE_Pattern. Mais Python l'a également redéfini comme une fonction du module re :
exemple :
re.search(patron, texte, re.IGNORECASE))...
Pour la clarté de l'exposé, on s'en tient à une seule syntaxe, celle du script ci-dessus, qui a l'avantage
de ressembler à ce qui se fait en java.
Copier et exécuter le code.
Justifier les résultats.
Ecrire ici vos réponses.
La partie précède a pour objectif de spécifier une syntaxe : celle requise par le module re pour faire des opérations assez semblables à celles réalisées avec plus de simplicité.
Quel est l'apport du module re pour les opérations de recherche, de comparaison, de substitution, de découpage de chaînes ? Lorsque l'on fait une recherche ou une substitution dans un traitement de texte ou un éditeur, la chaîne recherchée doit être explicite.
On peut imposer de ne pas différencier majuscules et minuscules, ou de ne rechercher que des mots entiers ; ces aménagements sont insuffisants.
Remarque : Les éditeurs et traitements de texte actuels peuvent travailler différemment !
On peut souhaiter disposer, pour écrire les patrons, de jokers (comme le * ou le ?) ou de conditions (exemple : trouver les virgules qui sont suivies d'un caractère alphabétique ; trouver les espaces multiples ; se limiter aux caractères alphanumériques).
Les expressions régulières sont des chaînes comportant des jokers et des éléments de description de chaînes de caractères.
La liste des jokers avec les regexp sont les suivants :
Signe | Signification générale |
. | le point remplace tout caractère sauf le saut de ligne (\\n). sous DOTALL, le point représente tout caractère, y compris le saut de ligne. |
^ | Le chevron (circonflexe) représente le début de la chaîne analysée. sous MULTILINE, représente en plus la position après le saut de ligne |
$ | Le dollar représente la fin de la chaîne analysée. sous MULTILINE, représente en plus la position avant le saut de ligne. |
Des exemples d'utilisation des jokers :
Si on met \"azer.tyiop\" : cette expression régulière correspond à : azer suivi de n'importe quel
caractère, suivi de tyiop sur une ligne.
En mode DOTALL, le caractère peut être le saut de ligne.
Si nous sommes en recherche, on aura comme résultat: azeratyiop, azerAtyiop, azer(tyiop, azer.tyiop satisfont au modèle proposé.
Si on met \"^aze\" : le patron \"aze\" doit être recherché en début de texte uniquement en début de texte.
En mode MULTILINE, il est aussi recherché en début de chaque ligne.
Si on met \"tyiop$\" : le patron \"tyiop\" est recherché en fin de texte.
En mode MULTILINE, il est aussi recherché en fin de chaque ligne. \"^$\" : recherche d'un texte vide ou en mode MULTILINE d'une ligne vide.
Les symboles de répétitions d'un caractère sont les suivants :
itérateur | interprétation |
* | zéro, une ou plusieurs fois le caractère qui précède |
+ | une ou plusieurs fois le caractère qui précède |
? | zéro ou une fois le caractère qui précède |
{m} | exactement m fois le caractère qui précède |
{m,} | au moins m fois le caractère qui précède |
{m,n} | au moins m fois et au plus n fois le caractère qui précède |
Des exemples d'utilisations des symboles de répétition:
exp. reg. -> chaînes reconnues
ab*c -> ac, abc, abbc, abbbc, ...
ab+c -> abc, abbc, abbbc, ...
ab?c -> ac, abc
ab{2,}c -> abbc, abbbc, abbbbc, ....
ab{2,4}c -> abbc, abbbc, abbbbc
Lorsqu'une recherche est couronnée de succès, la partie de la chaîne comprise entre le début de celle-ci et la fin de la sous-chaîne trouvée est consommée. Ce qui signifie par exemple que la fonction findall() commence la recherche à partir du caractère suivant le dernier caractère consommé. La recherche est séquentielle et elle ne fait aucun retour en arrière.
Ecrire ici les résultats.
"}],[{"text":"Les itérateurs *, +, ? sont gourmands. C'est-à-dire que dans une recherche, ils ont un comportement qui conduit à reconnaître la plus grande chaîne possible. Ils consomment la chaîne au maximum, même si une correspondance a déjà été trouvée sur le patron proposé.
Par exemple, supposons que l'on ait :
texte = \"<h1>Expressions Régulières</h1>\"
patron = \"<.*>\"
Le sous-motif .* conduit à avoir le plus grand texte possible : l'expression régulière s'identifie à tout le texte.
Il faut lire patron comme :
le caractère < pour commencer ;
un maximum de caractères ;
le caractère > pour finir.
On aurait pu souhaiter au contraire une identification à <h1>, c'est-à-dire :
le caractère < pour commencer ;
un minimum de caractères ;
le caractère >.
Une nouvelle classe d'itérateurs réalisent ces opérations :
itérateur -> interprétation
*? -> zéro, une ou plusieurs fois le caractère qui précède ; non gourmand. Dans une expression, *? s'identifie à la plus petite chaîne possible.
+? -> une ou plusieurs fois le caractère qui précède ; non gourmand.
?? -> zéro ou une fois le caractère qui précède ; non gourmand.
{m,n}? -> le caractère qui précède m fois.
Application :
import re
texte = \"<<aaAAabbbccaaannn\"
print(\"le texte :\",texte)
patron = \"a{2,3}b?\"
cpatron = re.compile(patron, re.I)
res = cpatron.findall(texte)
print (\"patron :\",patron,\"résultat : \",res)
patron = \"a{2,3}?b?\"
cpatron = re.compile(patron, re.I)
res = cpatron.findall(texte)
print (\"patron :\",patron,\"résultat : \",res)
patron = \"a{2,3}b??\"
cpatron = re.compile(patron, re.I)
res = cpatron.findall(texte)
print (\"patron :\",patron,\"résultat : \",res)
Copier et tester le code.
Justifier le résultat.
","title":"Gourmandise."},{"edit":"Ecrire ici les résultats.
Les jokers et les opérateurs sont des caractères courants. Comment, dans une expression régulière peut-on distinguer ce caractère en tant que caractère et le même en tant qu'opérateur ou composant d'un opérateur?
On utilise le même système que Python dans ce cas : pour considérer un caractère comme se représentant lui-même, il faut l'échapper par un antislash. On aura donc pour le point \\., pour l'astérisque \\*, pour le signe plus \\+ et ainsi de suite.
La méthode search() permet de trouver la première sous-chaîne qui correspond à l'expression régulière donnée comme patron. On peut itérer la recherche grâce à la fonction findall(), qui retourne tous les éléments qui correspondent dans une liste de chaînes.
Application :
On dispose d'une liste de noms de localités et l'on se propose de rechercher celles dont le nom de termine par ville.
On ne distingue pas les majuscules et les minuscules dans la recherche.
import re
texte =\"Ablon\\nAcqueville\\nAgy\\nAigner-Ville\\nAiran\\nAmayé-sur-Orne\\
\\nAmblie\\nAmfreville\\nAngervillers\\nAngoville\\nArganchy\\nArgences\\
\\nArromanches-les-Bains\\nAsnelles\\nAsnières-Surville\"
print(\"le texte\",texte,\"\\n\")
patron = \".*ville$\"
cpatron = re.compile (patron)
resultat = cpatron.findall(texte)
print (\"exemple 1: \",resultat, \"\\n\")
cpatron = re.compile (patron, re.MULTILINE)
resultat = cpatron.findall(texte)
print (\"exemple 2: \",resultat, \"\\n\")
cpatron = re.compile (patron, re.MULTILINE+re.IGNORECASE)
resultat = cpatron.findall(texte)
print (\"exemple 3: \",resultat, \"\\n\")
Ecrire et tester le code.
Justifier les résultats.
","title":"Des méthodes à recherches multiples"},{"edit":"Ecrire ici les résultats.
La syntaxe est la suivante :
cpatron.sub (remplacement, texte, [count])
Retourne le texte avec ses remplacements.
La valeur remplacement est une chaîne (qui peut être obtenue par application d'une fonction, appelée à chaque remplacement).
count fixe le nombre maximum de remplacements ; 0 est la valeur par défaut et signifie (paradoxalement) que tous les remplacements possibles doivent être effectués.
On a aussi la syntaxe :
cpatron.subn (remplacement, texte, count)
Renvoie un tuple comportant la nouvelle chaîne et le nombre de remplacements.
Application :
# substitution dans une chaîne
import re
texte = \"Retourne le texte avec ses remplacements. La \\
valeur remplacement est une chaîne (qui peut être obtenue \\
par application d'une fonction, appelée à chaque \\
remplacement). count donne le maximum de remplacements ; \\
0 est la valeur par défaut et signifie que tous les remplacements\\
possibles doivent être effectués.\"
print(\"le texte\",texte,\"\\n\")
patron= \"\\. \" # antislash de protection du point
remplacement =\"\\n\\n\"
cpatron = re.compile(patron)
nouveau = cpatron.sub(remplacement, texte)
print (nouveau)
print (\"\\n************************************\\n\")
retTuple = cpatron.subn (remplacement, texte)
print (retTuple)
Ecrire et tester le code.
Justifier les résultats.
Ecrire ici les résultats.
La syntaxe est la suivante :
cpatron.split(texte, [maxsplit])
Pour mémoire, reprenons l'application 1 avec split() au lieu de findall()
import re
texte =\"Ablon\\nAcqueville\\nAgy\\nAigner-Ville\\nAiran\\nAmayé-sur-Orne\\
\\nAmblie\\nAmfreville\\nAngervillers\\nAngoville\\nArganchy\\nArgences\\
\\nArromanches-les-Bains\\nAsnelles\\nAsnières-Surville\"
print(\"le texte\",texte,\"\\n\")
patron = \".*ville$\"
cpatron = re.compile(patron)
resultat = cpatron.split(texte)
print (\"exemple 1: \",resultat, \"\\n\")
cpatron = re.compile (patron, re.MULTILINE)
resultat = cpatron.split(texte)
print (\"exemple 2: \",resultat, \"\\n\")
cpatron = re.compile (patron, re.MULTILINE+re.IGNORECASE)
resultat = cpatron.split(texte)
print (\"exemple 3: \",resultat, \"\\n\")
Ecrire et tester le code.
Justifier les résultats par rapport à la fonction findall().
Ecrire ici les résultats.
Faites suivant et envoyez votre travail au format pdf à l'adresse mail ci-dessous :
Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.