Apprenez les bases et les astuces des expressions canoniques Python à partir de zéro

À propos des expressions régulières Python. Jusqu'à présent, je recherchais sur Google et je l'ai mis en œuvre si nécessaire, mais j'ai pensé qu'il était temps d'approfondir ma compréhension. On dit que cela semble génial de "rechercher et mettre en œuvre si nécessaire", mais c'est un niveau débutant. J'écris avec une conscience de ** ce que les débutants devraient apprendre de zéro ** et ** de ce que l'utilisateur occasionnel réapprendra **. Dans cet article, Knock 100 Language Processing 2015 ["Chapter 3: Regular Expressions"](http://www.cl. ecei.tohoku.ac.jp/nlp100/#ch3) est organisé.

Lien de référence

Lien Remarques
Expression régulière HOWTO Expression régulière officielle Python Comment faire
re ---Opération d'expression régulière Description officielle du paquet Python re

De base

Python utilise Package re pour implémenter des expressions régulières. Dans les instructions Python suivantes, ʻimport re` est omis.

import re

Deux façons d'utiliser

1. Utilisez la fonction directement

Utilisez des fonctions telles que «re.match» et «re.sub».

#Le premier argument est un modèle d'expression régulière(Terme de recherche), Le deuxième argument est la cible de recherche
result = re.match('Hel', 'Hellow python')

print(result)
# <_sre.SRE_Match object; span=(0, 3), match='Hel'>

print(result.group())
# Hel

2. Compiler et utiliser

Utilisez des fonctions telles que «match» et «sub» après avoir compilé le modèle d'expression régulière.

#Compilez le modèle d'expression régulière à l'avance
regex = re.compile('Hel')

result = regex.match('Hellow python')

print(result)
# <_sre.SRE_Match object; span=(0, 3), match='Hel'>

print(result.group())
# Hel

Deux types d'utilisation

** Si vous souhaitez utiliser plusieurs modèles d'expressions régulières plusieurs fois, utilisez la méthode de compilation **. Officiel a la description suivante.

Il est plus efficace d'utiliser re.compile () pour enregistrer et réutiliser l'objet d'expression canonique résultant lorsque vous utilisez cette expression plusieurs fois dans un programme. Les derniers modèles passés à re.compile () et les fonctions de correspondance au niveau du module sont mis en cache au fur et à mesure qu'ils ont été compilés, de sorte que les programmes qui n'utilisent que quelques expressions régulières à la fois n'ont pas besoin de compiler des expressions régulières.

Si vous utilisez le même modèle d'expression régulière plusieurs fois, il ne semble y avoir aucun avantage de vitesse lors de la compilation. Je n'ai pas vérifié combien il est mis en cache.

Définition du modèle d'expression régulière (phrase de recherche)

Séquence d'échappement désactivée pour la chaîne brute

La chaîne brute n'est pas une rubrique spécifique à une expression régulière, mais elle peut être utilisée pour ** désactiver les séquences d'échappement **.

Dans le premier cas de l'exemple suivant, \ t devient une tabulation et \ n devient une ligne de rupture, mais dans le dernier cas, elle est traitée comme une chaîne de caractères \ t, \ n telle quelle.

print('a\tb\nA\tB')
print(r'a\tb\nA\tB')

Résultat de sortie du terminal


a	b
A	B

a\tb\nA\tB

** Je ne veux pas écrire une séquence d'échappement pour les barres obliques inverses dans le modèle d'expression régulière, donc j'utilise une chaîne brute **

result = re.match(r'\d', '329')

Articles "Ecrire des expressions régulières à l'aide de chaînes Python brutes" et "Ignorer (désactiver) les séquences d'échappement en Python" La chaîne brute " a une explication détaillée.

Ignorez les sauts de ligne, les commentaires et les espaces avec des guillemets triples et re.VERBOSE

Vous pouvez utiliser des sauts de ligne dans votre modèle d'expression régulière en les entourant de guillemets triples `` '' (qui peuvent être "" ") (aucun saut n'est acceptable). Vous pouvez exclure les espaces et les commentaires des modèles d'expression régulière en passant re.VERBOSE. ** Les citations Ripple et re.VERBOSE` le rendent très lisible ** Il est facile de voir si vous écrivez le modèle d'expression régulière suivant.

a = re.compile(r'''\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits''', re.VERBOSE)

Vous pouvez en savoir plus sur les guillemets triples dans l'article "Générer des chaînes en Python (guillemets, constructeurs str)" (https://note.nkmk.me/python-str-literal-constructor/).

Au fait, si vous souhaitez utiliser plusieurs indicateurs de compilation dans les indicateurs de paramètre compile, vous pouvez simplement ajouter+(addition).

a = re.compile(r'''\d''', re.VERBOSE+re.MULTILINE)

Caractère spécial

lettre La description Remarques Exemple Rencontre Ne correspond pas
\d Nombres [0-9]Pareil que
\D Autre que des nombres [^0-9]Pareil que
\s Caractère vierge [\t\n\r\f\v]Pareil que
\S Autres que les caractères blancs [^\t\n\r\f\v]Pareil que
\w Alphabet et soulignement [a-zA-Z0-9_]Pareil que
\W Caractères non alphabétiques [\a-zA-Z0-9_]Pareil que
\A Le début de la chaîne ^Semblable à
\Z Fin de chaîne $Semblable à
\b Limites de mots(espace)
. Toute lettre simple - 1.3 123, 133 1223
^ Le début de la chaîne - ^123 1234 0123
$ Fin de chaîne - 123$ 0123 1234
* Répétez 0 fois ou plus - 12* 1, 12, 122 11, 22
+ Répétez une ou plusieurs fois - 12+ 12, 122 1, 11, 22
? 0 fois ou 1 fois - 12? 1, 12 122
{m} Répéter m fois - 1{3} 111 11, 1111
{m,n} Répéter m ~ n fois - 1{2, 3} 11, 111 1, 1111
[] ensemble [^5]Puis autre que 5 [1-3] 1, 2, 3 4, 5
| Ensemble de somme(or) - 1|2 1, 2 3
() Regroupement - (12)+ 12, 1212 1, 123

Fonction de correspondance

J'utilise souvent les fonctions suivantes.

une fonction Objectif
match De la cordeAu débutDéterminez s'il correspond à l'expression régulière
search Trouvez où l'expression régulière correspond
findall Recherche toutes les sous-chaînes correspondantes et retourne sous forme de liste
sub Remplacement de la chaîne

match et recherche .html # re.search)

«Re.match» ne correspond qu'au début de la chaîne, et «re.search» correspond quelle que soit la position dans la chaîne. Voir Official "search () vs. match ()" pour plus d'informations. Les deux renvoient uniquement le premier modèle (aucune correspondance après le second).

>>> re.match("c", "abcdef")    #Le début est"c"Ne correspond pas car ce n'est pas
>>> re.search("c", "abcdef")   #Rencontre
<re.Match object; span=(2, 3), match='c'>

Le résultat est dans «groupe». Tous les résultats sont contenus dans groupe (0), et les résultats de la recherche groupée sont numérotés séquentiellement à partir de 1.

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # The entire match
'Isaac Newton'
>>> m.group(1)       # The first parenthesized subgroup.
'Isaac'
>>> m.group(2)       # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2)    # Multiple arguments give us a tuple.
('Isaac', 'Newton')

findall Findall renvoie toutes les chaînes qui correspondent au modèle au format liste.

>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']

Vous pouvez spécifier la cible de capture en utilisant (), mais si vous en spécifiez plusieurs, ce sera comme suit. Il sera retourné sous forme de taple pour chaque groupe.

>>> print(re.findall(r'''(1st)(2nd)''', '1st2nd1st2nd'))
[('1st', '2nd'), ('1st', '2nd')]

sub Remplacez les caractères. Dans l'ordre des arguments, 1. le modèle d'expression régulière, 2. la chaîne de caractères après le remplacement et 3. la chaîne de caractères à remplacer.

>>> re.sub(r'Avant le remplacement', 'Après remplacement', 'Avant le remplacement 対象外 Avant le remplacement')
'Après le remplacement Non applicable Après le remplacement'

Compiler les drapeaux

Voici les indicateurs de compilation qui sont souvent utilisés. Passez-le au paramètre de fonction flags.

drapeau sens
DOTALL .À n'importe quel caractère, y compris les sauts de ligne
IGNORECASE Insensible à la casse
MULTILINE ^Ou$Correspond aux chaînes de caractères multilignes avec.
VERBOSE Ignorer les commentaires et les espaces dans les expressions régulières

Je vais vous expliquer un peu plus en détail sauf pour le VERBOSE et ceux qui sont difficiles à comprendre.

DOTALL re.DOTALL est une option pour inclure un saut de ligne pour le caractère générique . (DOT).

string = r'''\
1ère ligne
2e ligne au début de la ligne'''

print(re.findall(r'1st.*2nd', string, re.DOTALL))
# ['1st line\n ligne commençant la 2ème']

print(re.findall(r'1st.*2nd', string))
# No Match

Voir l'article Python: Remplacement de la correspondance multiligne par des expressions régulières pour plus de détails.

MULTILINE Utilisez cette option lorsque vous souhaitez rechercher plusieurs lignes. Dans l'exemple ci-dessous, si vous utilisez re.MULTILINE, la deuxième ligne (" le début de la deuxième ligne ") sera également la cible. * Dans le cas de la fonction match, il n'a pas de sens d'utiliser re.MULTILINE

string = r'''\
1ère ligne
2e ligne au début de la ligne'''

print(re.findall(r'^Début de ligne.*', string, re.MULTILINE))
# ['1ère ligne', '2e ligne au début de la ligne']

print(re.findall(r'^Début de ligne.*', string))
# ['1ère ligne']

Voir l'article Python: Remplacement de la correspondance multiligne par des expressions régulières pour plus de détails.

Tips

Non soumis à la capture

Si vous ajoutez (?: ...), il ne sera pas inclus dans la chaîne de résultat de la recherche ** et ne sera pas capturé. La Syntaxe des expressions régulières explique ce qui suit.

Une version non capturée de parenthèses régulières. Correspond à une expression régulière entre parenthèses, mais les sous-chaînes mises en correspondance par ce groupe ne peuvent pas être récupérées une fois la correspondance effectuée ou référencées ultérieurement dans le modèle.

Dans l'exemple ci-dessous, la partie «4» est utilisée comme modèle d'expression régulière, mais elle n'est pas sortie dans le résultat.

>>> re.findall(r'(.012)(?:4)', 'A0123 B0124 C0123')
['B012']

Match gourmand / non gourmand

** Vous pouvez contrôler la longueur de la chaîne de caractères cible du résultat de la recherche **. ** La correspondance de longueur maximale est une correspondance gourmande et la correspondance de longueur minimale est une correspondance non gourmande **. La valeur par défaut est une correspondance gourmande, et pour la rendre non gourmande, attachez ? Aux caractères spéciaux continus (*,?, +). Voici des exemples de phrases des deux.

#Match gourmand
>>> print(re.findall(r'.0.*2',  'A0123 B0123'))
['A0123 B012']

#Match non gourmand(*Après le?)
>>> print(re.findall(r'.0.*?2', 'A0123 B0123'))
['A012', 'B012']

Voir l'article "Matchs gourmands et non gourmands" pour plus d'informations.

Retour référence

Vous pouvez utiliser \ number pour faire correspondre le contenu du groupe précédent. Dans Official Syntax, la description suivante.

Correspond au contenu du groupe avec le même numéro. Les groupes peuvent être numérotés en commençant par 1. Par exemple, (. +) \ 1 correspond à "le" ou "55 55", mais pas à "le" (notez l'espace après le groupe). Cette séquence spéciale ne peut être utilisée que pour correspondre à l'un des 99 premiers groupes. Si le premier chiffre du nombre est 0 ou si le nombre est un nombre octadécimal à 3 chiffres, il est interprété comme un caractère avec le nombre octadécimal, et non comme une correspondance de groupe. Tous les échappements numériques entre les classes de caractères «[» et «]» sont traités comme des caractères.

Plus précisément, comme ceci, la partie \ 1 correspond à l'abcab dans la même signification que la partie correspondant à la précédente (ab), mais abddd n'a pas les 4e et 5e caractères ab. Ne correspond pas.

>>> print(re.findall(r'''(ab).\1''', 'abcab abddd'))
['ab']

Affirmation d'anticipation / d'anticipation

Bien qu'il ne soit pas inclus dans la cible de correspondance, il existe les quatre manières suivantes de l'utiliser pour inclure ou non la chaîne de caractères dans la condition de recherche.

La forme suivante est utilisée comme matrice.

positif le déni
Regard vers l’avenir (?=...)
...Match si la partie continue ensuite
(?!...)
...Match si la pièce ne suit pas
Regard vers l’avenir (?<=...)
...Correspondance si la pièce est avant la position actuelle et qu'il y a correspondance
(?<!...)
...Correspondance si la pièce est avant la position actuelle et qu'il n'y a pas de correspondance

Un exemple concret est plus facile à comprendre qu'une explication détaillée.

>>> string = 'A01234 B91235 C01234'

#Affirmation affirmative d'anticipation(Positive Lookahead Assertions)
# '123'À côté de'5'Chaîne de caractères suivie de('(?=5)'Une partie est la suivante'.'Ne t'en passe pas)
>>> print(re.findall(r'..123(?=5).', string))
['B91235']

#Affirmation d'anticipation négative(Negative Lookahead Assertions)
# '123'À côté de'5'Chaîne de caractères qui ne suit pas('(?!5)'Une partie est la suivante'.'Ne t'en passe pas)
>>> print(re.findall(r'..123(?!5).', string))
['A01234', 'C01234']

#Affirmation affirmative d'anticipation(Positive Lookbehind Assertions)
# '0'Mais'123'Chaîne correspondante avant('(?<=0)'La partie de est le début'.'Maisなければ取得しない)
>>> print(re.findall(r'..(?<=0)123', string))
['A0123', 'C0123']

#Affirmation d'anticipation négative(Negative Lookbehind Assertions)
# '0'Mais'123'Chaîne sans correspondance avant('(?<!0)'La partie de est le début'.'Maisなければ取得しない)
>>> print(re.findall(r'..(?<!0)123', string))
['B9123']

Recommended Posts

Apprenez les bases et les astuces des expressions canoniques Python à partir de zéro
Expressions régulières faciles et solides à apprendre en Python
Apprenez les méthodes M-H et HMC en lisant les statistiques bayésiennes à partir des bases
(Python) Remarques sur la lecture de HTML et l'utilisation d'expressions régulières
Portage et modification du solveur de doublets de python2 vers python3.
[Python] Comment lire les données de CIFAR-10 et CIFAR-100
Lier PHP et Python à partir de zéro sur Laravel
Astuces Python et Numpy
Changements de Python 3.0 à Python 3.5
Changements de Python 2 à Python 3.0
mémo d'expression régulière python
Expression régulière en Python
Conseils et précautions lors du portage des programmes MATLAB vers Python
Publier de Python vers Slack
Feuille de route d'apprentissage qui vous permet de développer et de publier des services à partir de zéro avec Python
Notes sur l'expression régulière de la théorie Python
Comment se connecter à diverses bases de données à partir de Python (PEP 249) et SQL Alchemy
Anaconda mis à jour de 4.2.0 à 4.3.0 (python3.5 mis à jour vers python3.6)
Méthode d'apprentissage TensorFlow pour les professionnels des arts libéraux et les débutants en Python
Conseils pour coder courts et faciles à lire en Python
Convertir le projet Scratch en Python
Passer de python2.7 à python3.6 (centos7)
bases de python: conditions et itérations
[Introduction to Data Scientists] Bases de Python ♬ Fonctions et classes
Connectez-vous à sqlite depuis python
Manipulation d'expressions régulières par Python
À propos de Python et des expressions régulières
~ Conseils pour les débutants de Python présentés avec amour par Pythonista ③ ~
Aller au langage pour voir et se souvenir de la partie 8 Appeler le langage GO à partir de Python
[Python] Hit Keras depuis TensorFlow et TensorFlow depuis c ++ pour accélérer l'exécution.
J'ai essayé de créer une expression régulière de "montant" en utilisant Python
Comment obtenir des abonnés et des abonnés de Python à l'aide de l'API Mastodon
l'expression régulière de python, str et unicode sont sobres et addictives
J'ai essayé de créer une expression régulière de "temps" en utilisant Python
J'ai essayé de créer une expression régulière de "date" en utilisant Python
[Introduction to Data Scientists] Bases de Python ♬ Branchements conditionnels et boucles
[Il n'est pas trop tard pour apprendre Python à partir de 2020] Partie 3 Python Language Basic (1)
[Python] Essayez de reconnaître les caractères des images avec OpenCV et pyocr
[Introduction aux Data Scientists] Bases de Python ♬ Fonctions et fonctions anonymes, etc.
Appelez Matlab depuis Python pour optimiser
Python 3.6 sous Windows ... et vers Xamarin.
[Introduction à Python3 Jour 1] Programmation et Python
Python, rendement, retour et parfois rendement de
Programmation tirée des livres le 10 mai
Publication de Python sur la chronologie Facebook
[Lambda] [Python] Publier sur Twitter depuis Lambda!
Lire et utiliser des fichiers Python à partir de Python
À propos de Python, à partir et à l'importation, comme
Remplacement de chaîne par une expression régulière Python
Connectez-vous à la base de données utf8mb4 à partir de python
Python (de la première fois à l'exécution)
Publier une image de Python sur Tumblr
Conseils pour appeler Python à partir de C
Programmation tirée des livres le 7 mai
Journalisation Python et vidage vers json
Comment accéder à wikipedia depuis python
Python pour passer d'une autre langue