À 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 | 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 |
Python utilise Package re
pour implémenter des expressions régulières. Dans les instructions Python suivantes, ʻimport re` est omis.
import re
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
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
** 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.
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.
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)
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 |
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 |
«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'
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
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']
** 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.
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']
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