Maison  >  Article  >  développement back-end  >  Un guide plus détaillé des opérations sur les expressions régulières Python

Un guide plus détaillé des opérations sur les expressions régulières Python

巴扎黑
巴扎黑original
2017-05-21 11:16:381649parcourir

Python a ajouté le module re depuis la version 1.5, qui fournit des modèles d'expressions régulières de style Perl. Les versions antérieures à Python 1.5 fournissaient des modèles de style Emecs via le module regex. Le mode de style Emacs est légèrement moins lisible et moins puissant, alors essayez de ne pas utiliser le module regex lors de l'écriture d'un nouveau code. Bien sûr, vous pouvez parfois en trouver des traces dans l'ancien code.

De par leur nature même, les expressions régulières (ou RE) sont un petit langage de programmation hautement spécialisé intégré à Python et implémenté via le module re. En utilisant ce petit langage, vous pouvez spécifier des règles pour un ensemble de chaînes correspondant auquel vous souhaitez faire correspondre ; cet ensemble de chaînes peut contenir des phrases en anglais, des adresses e-mail, des commandes TeX ou tout ce que vous voulez. Vous pouvez ensuite poser des questions telles que « Cette chaîne correspond-elle au modèle ? » ou « Une partie de cette chaîne correspond-elle au modèle ? ». Vous pouvez également utiliser RE pour modifier ou diviser des chaînes de différentes manières.


Les modèles d'expressions régulières sont compilés dans une série de bytecodes puis exécutés par un moteur de correspondance écrit en C. Dans une utilisation avancée, on peut également vouloir prêter une attention particulière à la façon dont le moteur exécute un RE donné et à la façon dont le RE est écrit d'une manière spécifique pour accélérer l'exécution du bytecode produit. Cet article ne couvre pas l'optimisation, car cela nécessite que vous compreniez parfaitement les mécanismes internes du moteur de correspondance.


Le langage des expressions régulières est relativement petit et restreint (fonctionnalité limitée), donc tous les traitements de chaînes ne peuvent pas être effectués avec des expressions régulières. Bien sûr, certaines tâches peuvent être accomplies avec des expressions régulières, mais au final, les expressions deviendront extrêmement complexes. Lorsque vous rencontrez ces situations, il peut être préférable d'écrire du code Python pour le gérer ; bien que le code Python soit plus lent qu'une expression régulière sophistiquée, il est plus facile à comprendre.

Mode simple

Nous commencerons par l'apprentissage des expressions régulières le plus simple. Étant donné que les expressions régulières sont souvent utilisées pour la manipulation de chaînes, commençons par la tâche la plus courante : la correspondance de caractères.


Pour une explication détaillée de l'informatique sous-jacente aux expressions régulières (automates finis déterministes et non déterministes), vous pouvez consulter n'importe quel manuel sur l'écriture de compilateurs.

Correspondance des caractères

La plupart des lettres et des caractères se correspondent généralement. Par exemple, le test d'expression régulière correspondra exactement à la chaîne "test". (Vous pouvez également utiliser le mode insensible à la casse, ce qui fera également correspondre ce RE à "Test" ou "TEST" ; nous en reparlerons plus tard.)

Il y a bien sûr des exceptions à cette règle, certains caractères plutôt spéciaux ; , ils ne correspondent pas eux-mêmes, mais indiquent qu'ils doivent correspondre à quelque chose de spécial, sinon ils affecteront le nombre de répétitions d'autres parties du RE. Une grande partie de cet article est consacrée à la discussion de divers métacaractères et de leurs fonctions.

Voici une liste complète des métacaractères ; leurs significations sont discutées dans le reste de ce guide.

. ^ $ * + ? | ( )Les métacaractères que nous examinons en premier sont "[" et "]". Ils sont souvent utilisés pour spécifier une catégorie de caractères, c'est-à-dire un jeu de caractères auquel vous souhaitez faire correspondre. Les caractères peuvent être répertoriés individuellement, ou deux caractères donnés séparés par un signe "-" peuvent être utilisés pour représenter une plage de caractères. Par exemple, [abc] correspondra à n'importe quel caractère parmi « a », « b » ou « c » ; vous pouvez également utiliser l'intervalle [a-c] pour représenter le même jeu de caractères, ce qui a le même effet que le premier. Si vous souhaitez uniquement faire correspondre les lettres minuscules, alors RE doit être écrit sous la forme [a-z]. Le métacaractère

ne fonctionne pas dans les catégories. Par exemple, [akm$] correspondra à n'importe lequel des caractères « a », « k », « m » ou « $ » ; « $ » est généralement utilisé comme métacaractère, mais dans la classe de caractères, ses caractéristiques sont supprimées. , Revenir aux caractères normaux.

Vous pouvez utiliser le complément pour faire correspondre les caractères qui ne sont pas dans la plage. La méthode consiste à utiliser « ^ » comme premier caractère de la catégorie ; « ^ » ailleurs correspondra simplement au caractère « ^ » lui-même. Par exemple, [^5] correspondra à n'importe quel caractère sauf « 5 ».

Le métacaractère le plus important est peut-être la barre oblique inverse """. En tant que lettre de chaîne en Python, différents caractères peuvent être ajoutés après la barre oblique inverse pour exprimer différentes significations spéciales. Il peut également être utilisé pour annuler tous les métacaractères. caractères afin que vous peut les faire correspondre dans un modèle. Par exemple, si vous devez faire correspondre les caractères "[" ou """, vous pouvez les faire précéder d'une barre oblique inverse pour supprimer leur signification particulière : "[ ou " ".

Certains jeux de caractères prédéfinis représentés par des caractères spéciaux commençant par """ sont généralement utiles, comme les chiffres, les lettres ou d'autres jeux de caractères non vides. Voici les caractères spéciaux prédéfinis disponibles :

# !python

>>> importer re

>>> p = re.compile( 'ab*')

>>> imprimer p

<instance re.RegexObject à 80b4150>

re.compile() accepte également les paramètres d'indicateur facultatifs, qui sont souvent utilisés pour implémenter différentes fonctions spéciales et changements de syntaxe. Nous examinerons tous les paramètres disponibles plus tard, mais pour l'instant juste un exemple :

#!python

>> ;> p = re.compile('ab*', re.IGNORECASE)

RE est envoyé à re.compile() sous forme de chaîne. Les RE sont traités comme des chaînes car les expressions régulières ne font pas partie intégrante du langage Python et aucune syntaxe spécifique n'a été créée pour elles. (Les applications n'ont tout simplement pas besoin de RE, il n'est donc pas nécessaire de gonfler la spécification du langage en les incluant.) Le module re est simplement inclus dans Python en tant que module d'extension C, tout comme les modules socket ou zlib.


Utilisez les RE comme chaînes pour garantir la simplicité du langage Python, mais cela entraîne un problème comme mentionné dans le titre de la section suivante.

Problèmes de barre oblique inverse

Dans les réglementations antérieures, les expressions régulières utilisaient le caractère barre oblique inverse (""") pour indiquer un formatage spécial ou pour permettre l'utilisation d'un caractère spécial sans appeler son utilisation spéciale. Cela entre en conflit avec l'utilisation par Python des mêmes caractères dans les chaînes.


Disons que vous voulez écrire un RE pour correspondre à la chaîne ""section". Vous cherchez probablement dans un fichier LATEX. Afin de juger le code du programme, écrivez d’abord la chaîne à laquelle vous souhaitez faire correspondre. Ensuite, vous devez faire précéder toutes les barres obliques inverses et les métacaractères d'une barre oblique inverse pour supprimer leur signification particulière.

字符 阶段
section 要匹配的字符串
\section 为 re.compile 取消反斜杠的特殊意义
"\section" 为字符串取消反斜杠


En termes simples, pour faire correspondre une barre oblique inverse, vous devez écrire '\' dans la chaîne RE, car l'expression régulière doit être "\", et chaque barre oblique inverse doit être représenté par "\" selon la convention de représentation des lettres et chaînes Python. Cette nature répétitive des barres obliques inverses dans les RE entraîne un grand nombre de barres obliques inverses répétées et les chaînes qui en résultent sont difficiles à comprendre.


La solution consiste à utiliser la représentation de chaîne brute de Python pour les expressions régulières ; en ajoutant une barre oblique inverse "r" avant que la chaîne ne soit traitée d'une manière particulière, donc r"n " est deux caractères contenant " " et "n", et "n" est un caractère, représentant une nouvelle ligne. Les expressions régulières sont généralement représentées par cette chaîne brute dans le code Python.

常规字符串 Raw 字符串
"ab*" r"ab*"
"\section" r"\section"
"\w+\s+" r"w+s+1"

Effectuer une correspondance

Une fois que vous avez un objet d'expression régulière compilé, qu'en faites-vous ? Les instances `RegexObject` ont certaines méthodes et propriétés. Seuls les plus importants sont présentés ici. Si vous souhaitez voir la liste complète, veuillez consulter la référence de la bibliothèque Python

方法/属性 作用
match() 决定 RE 是否在字符串刚开始的位置匹配
search() 扫描字符串,找到这个 RE 匹配的位置
findall() 找到 RE 匹配的所有子串,并把它们作为一个列表返回
finditer() 找到 RE 匹配的所有子串,并把它们作为一个迭代器返回
.


Si aucune correspondance n'est trouvée, match() et search() renverront None. En cas de succès, une instance `MatchObject` sera renvoyée, qui contient des informations sur la correspondance : où elle commence et se termine, la sous-chaîne à laquelle elle correspond, etc.

Vous pouvez l'apprendre en utilisant le dialogue homme-machine et en expérimentant le module re. Si vous disposez de Tkinter, vous pouvez envisager de consulter Tools/scripts/redemo.py, un programme de démonstration inclus avec la distribution Python.

Tout d'abord, lancez l'interpréteur Python, importez le module re et compilez un RE :

#!python

Python
2.2.2 (#1, 10 février 2003, 12:57:01)

>>> importer re

>>> p = re.compile(' [a-z]+')

>>>p

<_sre.SRE_Pattern objet à 80c3c28>


Maintenant, vous pouvez essayer d'utiliser RE [a-z]+ pour faire correspondre différentes chaînes. Une chaîne vide ne correspondra pas du tout, puisque + signifie « une ou plusieurs répétitions ». Dans ce cas, match() renverra None car il ne laisse l'interpréteur sans sortie. Vous pouvez comprendre cela en imprimant explicitement le résultat de match().

# !python

>>> p.match("")

>>> imprimer p.match ("")

Aucun

Maintenant, essayons de l'utiliser pour faire correspondre une chaîne comme " tempo ". Dans ce cas, match() renverra un MatchObject. Vous pouvez donc enregistrer le résultat dans une variable pour une utilisation ultérieure.

# !python

>>> m =p.match('tempo')

>> > >>Vous pouvez désormais interroger `MatchObject` pour obtenir des informations connexes sur les chaînes correspondantes. Les instances MatchObject ont également plusieurs méthodes et propriétés ; les plus importantes sont les suivantes :


Essayez ces méthodes et vous comprendrez bientôt leurs effets :

#!python

> > m.group()

'tempo'

>>> m.start(), m.end()

(0,
5 )

>>> m.span()

(0,
5)

group() renvoie la sous-chaîne correspondant à RE. start() et end() renvoient l'index auquel la correspondance commence et se termine. span() renvoie les indices de début et de fin ensemble dans un seul tuple. Parce que la méthode match vérifie que si RE commence à correspondre au début de la chaîne, alors start() sera toujours nul. Cependant, la méthode de recherche d'une instance `RegexObject` analyse la chaîne suivante, auquel cas la correspondance peut commencer à une position autre que zéro.

# !python

>>> imprimer p.match('::: message')

Aucun

>>> m = p.search('::: message') ; imprimer m

<Instance re.MatchObject à 80c9650>

>>> m. group()

'message'

> >> m.span()

(
4, 11)

Dans les programmes réels, l'approche la plus courante consiste à enregistrer `MatchObject` dans une variable, puis à vérifier s'il s'agit de None, généralement comme suit :

# !python

p
= re.compile( )

m
= p.match( 'la chaîne va ici' )

if m:

imprimer 'Match trouvé : ', m.group()

else:

print 'Aucune correspondance'

Deux méthodes `RegexObject` renvoie toutes les sous-chaînes correspondant au modèle. findall() renvoie une liste de lignes de chaînes correspondantes :

#!python

>>> p = re.compile('" d+')

>>> p.findall(' 12 batteurs tambourinant, 11 cornemuseurs sifflant, 10 seigneurs sautant')

[
' 12', '11', '10']

findall() a dû créer une liste lorsqu'il a renvoyé le résultat dans Python 2.2. , vous pouvez également utiliser la méthode finditer()

.

# !python

>>> itérateur = p.finditer('12 batteurs batteurs, 11  10 ')

>>> itérateur

<appelable-objet itérateur à 0x401833ac>

>>> pour match dans itérateur :

     
imprimer  match.span()



(0, 
2)

(
2224)

(
2931)

模块级函数

你不一定要产生一个 `RegexObject` 对象然後再调用它的方法;re 模块Il s'agit d'un match()、search()、sub() terminé. Il s'agit de `RegexObject`.要么是 Aucun 要么就是一个 `MatchObject` 的实例。

#!python

>>>  imprimer re.match(r'De"s+''Fromage amk')

Aucun

> ;>> re.match(r'De"s+''De amk jeudi 14 mai 19:12:10 1998')

<instance re.MatchObject à 80c5978>

Sous le capot, ces fonctions génèrent simplement un RegexOject et appellent les méthodes correspondantes dessus. Ils stockent également les objets compilés dans le cache, de sorte que les futurs appels utilisant le même RE seront plus rapides.


Utiliserez-vous ces fonctions au niveau du module, ou obtiendrez-vous d'abord un `RegexObject` puis appellerez-vous ses méthodes ? Celui que vous choisissez dépend de votre efficacité avec RE et de votre style de codage personnel. Si un RE n'est utilisé qu'une seule fois dans le code, les fonctions au niveau du module peuvent être plus pratiques. Si le programme contient beaucoup d'expressions régulières, ou réutilise la même à plusieurs endroits, il est plus utile de rassembler toutes les définitions et de compiler tous les RE à l'avance dans un bloc de code. Jetez un œil à un exemple de la bibliothèque standard, extrait du fichier xmllib.py :

#!python

réf
= re.compile( )

entityref
= re.compile( )

charref
= re.compile( )

starttagopen
= re.compile( )

Je préfère généralement utiliser des objets compilés, même s'ils ne sont utilisés qu'une seule fois, mais peu de gens seront aussi puristes que moi à ce sujet.

Drapeaux de compilation

Les indicateurs de compilation vous permettent de modifier une partie de la façon dont les expressions régulières s'exécutent. Dans le module re, le drapeau peut utiliser deux noms, l'un est le nom complet tel que IGNORECASE et l'autre est l'abréviation, sous forme d'une lettre telle que I. (Si vous êtes familier avec la modification du mode Perl, les formes à une lettre utilisent la même lettre ; par exemple, l'abréviation de re.VERBOSE est re.X.) Plusieurs indicateurs peuvent être spécifiés en les effectuant par un OU au niveau du bit. Par exemple, re.I | re.M est défini sur les drapeaux I et M :


Voici un tableau des drapeaux disponibles, avec des descriptions détaillées derrière chaque drapeau.

标志 含义
DOTALL, S 使 . 匹配包括换行在内的所有字符
IGNORECASE, I 使匹配对大小写不敏感
LOCALE, L 做本地化识别(locale-aware)匹配
MULTILINE, M 多行匹配,影响 ^ 和 $
VERBOSE, X 能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂

I
IGNORECASE

rend les classes de caractères et les chaînes de correspondance insensibles à la casse lors de la correspondance des lettres. Par exemple, [A-Z] peut également correspondre à des lettres minuscules, et Spam peut correspondre à « Spam », « spam » ou « spAM ». Cette lettre minuscule ne prend pas en compte la position actuelle.

L
LOCALE

Affecte "w, "W, "b et "B, en fonction de la configuration de localisation actuelle .

locales est une fonctionnalité de la bibliothèque C qui est utilisée pour aider à la programmation lorsque différentes langues doivent être prises en compte. Par exemple, si vous travaillez avec du texte français, vous souhaitez utiliser "w+" pour faire correspondre le texte, mais "w correspond uniquement à la classe de caractères [A-Za-z] ; il ne correspond pas à "é" ou "ç ". Si votre système est configuré correctement et que les paramètres régionaux sont définis sur le français, une fonction C interne indiquera au programme que « é » doit également être considéré comme une lettre. L'utilisation de l'indicateur LOCALE lors de la compilation d'une expression régulière entraînera un objet compilé qui utilise ces fonctions C pour gérer "w", ce qui sera plus lent, mais vous permettra toujours d'utiliser "w+ pour faire correspondre le texte français.

M
MULTILINE


(^ et $ ne seront pas interprétés pour le moment ; ils seront introduits dans la section 4.1 .)


Utilisez "^" pour faire correspondre uniquement le début de la chaîne, tandis que $ ne correspondra qu'à la fin de la chaîne et à la fin de la chaîne immédiatement avant une nouvelle ligne (s'il y en a une ). Lorsque cet indicateur est spécifié, "^" correspond au début de la chaîne et au début de chaque ligne de la chaîne. De même, le métacaractère $ correspond à la fin de la chaîne et à la fin de chaque ligne de la chaîne (directement avant chaque nouvelle ligne).

S
DOTALL

Faire en sorte que le caractère spécial "." corresponde exactement à n'importe quel caractère, y compris les nouvelles lignes sans cet indicateur, ". " Correspond à n'importe quel caractère sauf la nouvelle ligne.

Facile à comprendre. Lorsque cet indicateur est spécifié, les espaces dans la chaîne RE sont ignorés, sauf s'ils se trouvent dans une classe de caractères ou après une barre oblique inverse, ce qui vous permet d'organiser et d'indenter les RE plus clairement. Il permet également d'écrire des commentaires dans le RE, qui seront ignorés par le moteur ; les commentaires sont marqués d'un symbole "#", mais ce symbole ne peut pas venir après une chaîne ou une barre oblique inverse.
À titre d'exemple, voici un RE utilisant re.VERBOSE ; vous voyez à quel point il est plus facile de le lire ?


Mise en évidence de code réalisée par Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/


-->

#


#

!python
>>>
imprimer re.search('^De ', 'D'ici à l'éternité')
<
instance re.MatchObject à 80c1520>
>>> ;
imprimer re.search('^De', 'Réciter de mémoire')Aucun

$

correspond à la fin d'une ligne, qui est définie comme la fin de la chaîne ou n'importe quelle position après un caractère de nouvelle ligne

.

# !python

>>> imprimer re.search('}$''{block} ')

<instance re.MatchObject à 80adfa8>

>>> imprimer re.search('}$''{block} ' )

Aucun

>>> imprimer re. recherche('}$''{block}"n')

<instance re.MatchObject à 80adfa8>

匹配一个 "$",使用 "$ 或将其包含在字符类中,如[$]。

"A


只匹配字符串首。当不在 MULTILINE 模式,"A"只是匹配字符串首,而 ^ 还可以匹配在换行符之後字符串的任何位置。

"Z

Correspond uniquement à la fin de la chaîne.
只匹配字符串尾。

"b

单词边界。这是个零宽界定符(affirmations de largeur nulle)只用以匹配单词的词首和词尾。单词被定义为一个字母数字序列,因此词尾就是用空白符或非字母数字符来标示的。


下面的例子只匹配 "classe" 整个单词;而当它被包含在其他单词中时不匹配。

# !python

>>> p = re.compile(r'"bclass"b')

>>> imprimer p.search('pas de cours du tout')

<instance re.MatchObject à 80c8f28>

>>> imprimer p.search('l'algorithme déclassifié')

Aucun

>>> imprimer p.search('une sous-classe est')

Aucun

Il y a ici deux subtilités que vous devez garder à l'esprit lorsque vous utilisez cette séquence particulière. Le premier est le pire conflit entre les chaînes Python et les expressions régulières. Dans les chaînes Python, ""b" est un caractère barre oblique inverse et sa valeur ASCII est 8. Si vous n'utilisez pas de chaîne brute, alors Python convertira ""b" en caractère de secours, et votre RE Vous ne serez pas capable de l'assortir comme vous le souhaitez. L'exemple suivant ressemble à notre RE précédent, mais sans un « r » devant la chaîne RE.

# !python

>>> p = re.compile('"bclass"b')

> ;>> imprimer p.search('pas de cours du tout')

Aucun

>>> imprimer p.search('"b' + 'classe' + '"b')

<instance re.MatchObject à 80c3ee0> ;

Le deuxième est dans la classe de caractères, ce qualificatif (assertion) n'a aucun effet, "b représente le caractère de repli pour la compatibilité avec les chaînes Python.

" B


Une autre assertion de largeur nulle, qui est à l'opposé de "b et ne correspond que lorsque la position actuelle n'est pas à la limite d'un mot. >Groupe

Vous souvent Vous avez besoin d'obtenir plus d'informations que de savoir si le RE correspond. Les expressions régulières sont souvent utilisées pour analyser les chaînes. Écrivez un RE pour correspondre à la partie qui vous intéresse et divisez-le en plusieurs groupes. Par exemple, un en-tête RFC-822 est séparé en un nom d'en-tête. et une valeur par ":". Cela peut être fait en écrivant une expression régulière pour correspondre à l'en-tête entier, avec un groupe correspondant au nom de l'en-tête et l'autre groupe correspondant à l'en-tête. Les groupes

sont. identifiés par les métacaractères "(" et ")". "(" et ")" ont à peu près la même signification dans les expressions mathématiques. Regroupez les expressions qu'ils contiennent. Par exemple, vous pouvez utiliser des qualificatifs de répétition tels que *, +, ?, et {m,n} pour répéter le contenu du groupe, tel que (ab)* correspondra à zéro ou plusieurs doublons de "ab".


Mise en évidence de code réalisée par Actipro CodeHighlighter (freeware)
#
!python

>>>
p = re.compile('(ab)*')

>>>
imprimer p.match('ababababab').span()(0,

10
)

Les groupes sont spécifiés avec "(" et ")" et obtiennent les indices de début et de fin du texte auquel ils correspondent ; cela peut être fait avec un seul argument en utilisant group(), start(), end() et span(). Récupérer. Les groupes sont comptés à partir de 0. Le groupe 0 est toujours présent ; c'est l'intégralité du RE, donc les méthodes de `MatchObject` prennent toutes le groupe 0 comme argument par défaut. Nous verrons plus tard comment exprimer des étendues qui ne peuvent pas obtenir le texte auquel elles correspondent.

# !python

>>> p = re.compile('(a)b')

>>> m = p.match('ab')

>>> m.group()

'ab'

>>> m.group( 0)

'ab'

Le groupe est de Compter de gauche à droite, en commençant par 1. Les groupes peuvent être imbriqués. La valeur numérique du décompte peut être déterminée en comptant le nombre de parenthèses ouvertes de gauche à droite.

# !python

>>> p = re.compile('(a(b)c)d')

>>> m = p.match('abcd ')

>>> m.group(0)

'abcd'

>>> m.group(1)

'abc'

>>> m.group(2)

'b'

group() peut saisir plusieurs numéros de groupe à la fois , Dans ce cas, il renverra un tuple contenant les valeurs correspondant à ces groupes.

# !python

>>> m.group(2,1,2)

(
'b', 'abc', 'b')

La méthode groups() renvoie un tuple contenant toutes les chaînes de groupe, à partir de
1 au numéro de groupe contenu dans .

#!python

>>> ; m.groups()

(
'abc', 'b')

Les références arrière dans le motif vous permettent de spécifier le contenu d'un précédent en capturant le groupe , le groupe doit également être trouvé à la position actuelle dans la chaîne. Par exemple, si le contenu du groupe 1 peut être trouvé à l'emplacement actuel, "1 réussit, sinon il échoue. N'oubliez pas que les chaînes Python utilisent également des barres obliques inverses pour ajouter des données afin de permettre à la chaîne de contenir des caractères. Ainsi, dans RE, assurez-vous de utilisez des chaînes brutes lors de l'utilisation de références arrière. Par exemple, le RE suivant trouve des paires de mots dans une chaîne

Mise en évidence du code produit par Actipro CodeHighlighter (gratuit)

http://www.CodeHighlighter.com/
.

-->

## !python

>>> m = re.match("([abc])+", "abc")

>>> m.groups()

(
'c',)

>> ;> m = re.match("(?:[abc])+", "abc")

>>> m.groups()

()

En plus de capturer le contenu du groupe correspondant, aucun groupe de capture et capturer Un groupe se comporte exactement de la même manière ; vous pouvez y insérer n'importe quel caractère, vous pouvez le répéter avec des métacaractères répétitifs tels que "*", et vous pouvez l'imbriquer dans d'autres groupes (groupes de non-capture et groupes de capture). (?:...) est particulièrement utile pour modifier des groupes existants, puisque vous pouvez ajouter un nouveau groupe sans modifier tous les autres numéros de groupe. Il n’y a également aucune différence dans l’efficacité de la recherche entre les groupes capturants et non capturants, aucun des deux n’étant plus rapide que l’autre.


Deuxièmement, les groupes nommés sont plus importants et plus puissants, contrairement à la spécification de groupes avec des nombres, ils peuvent être spécifiés avec des noms ;


La syntaxe du groupe de commandes est une des extensions spécifiques à Python : (?P...). Le nom est évidemment le nom du groupe. Un groupe nommé est identique à un groupe de capture, sauf que le groupe a un nom. Les méthodes `MatchObject` acceptent soit un entier représentant le numéro de groupe, soit une chaîne contenant le nom du groupe lors de la gestion d'un groupe de capture. Les groupes nommés peuvent également être des nombres, vous pouvez donc obtenir des informations sur un groupe de deux manières :

#!python

> >> p = re.compile(r'(?P "b "w+"b)')

>>> m = p.search( '(((( Beaucoup de ponctuation )))' )

>>> m.group('mot' > ;>>
m.group(
1)'
Lots
'Les groupes nommés sont pratiques à utiliser car ils vous permettent d'utiliser des noms faciles à retenir au lieu d'avoir à mémoriser des nombres. En voici un du module imaplib RE : Mise en évidence de code réalisée par Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> # !python

InternalDate

#!python

>>> p = re.compile(r'(?P')

>>> p.search('Paris au printemps').group()

' le'

Délimiteur avant

Une autre assertion de largeur nulle est le délimiteur avant. Les délimiteurs avant incluent. les délimiteurs positifs vers l'avant et les délimiteurs positifs vers l'arrière, comme indiqué ci-dessous :

(?=...)

Symbole des délimiteurs positifs vers l'avant Si l'expression régulière contenue, représentée par. ... , réussit à la position actuelle, sinon il échoue, mais une fois l'expression contenue essayée, le moteur de correspondance ne s'améliore pas du tout ; le reste du modèle doit encore être défini

<.>(?!...)

L'opposé du délimiteur positif ; lorsque l'expression contenue ne peut pas être dans la chaîne. Succès lorsque la position actuelle correspond à

. aide à démontrer où le transfert peut réussir. Considérons un modèle simple qui correspond à un nom de fichier et le divise en un nom de base et un "." Par exemple, dans "news.rc", "news" est le. le nom de base et "rc" est l'extension du fichier

Le modèle de correspondance est très simple :


.
*[.].*$
Notez que "." nécessite un traitement spécial car il s'agit d'un métacaractère. Je le mets dans une classe de caractères. Notez également le $; à la fin. Ceci est ajouté pour garantir que toutes les parties restantes de la chaîne doivent être incluses dans l'extension. Cette expression régulière correspond à


Mise en évidence de code produite par Actipro CodeHighlighter (freeware)
"
foo.bar","autoexec.bat " , "sendmail.cf" et " imprimantes.conf".
Maintenant, pensez à rendre le problème un peu plus compliqué ; que se passe-t-il si vous souhaitez faire correspondre les noms de fichiers avec des extensions autres que "bat" ? Quelques tentatives incorrectes :

. *[.][^b].*$

La première tentative ci-dessus pour supprimer "bat" nécessite que le premier caractère de l'extension soit autre chose que "b". C'est faux car le modèle ne peut pas non plus correspondre à "foo.bar".

. *[.]([^b]..|.[ ^a].|..[^t])$

L'expression devient encore plus compliquée lorsque vous essayez de patcher la première solution pour exiger la correspondance de l'un des éléments suivants : le premier caractère de l'extension n'est pas "b" ; le deuxième caractère n'est pas "a" ou le troisième ; le caractère n'est pas "t". Cela accepterait "foo.bar" mais rejetterait "autoexec.bat", mais ne nécessiterait qu'une extension à trois caractères et n'accepterait pas une extension à deux caractères telle que "sendmail.cf". Nous allons encore compliquer le modèle au fur et à mesure que nous travaillons à le corriger.

. *[.]([^b].?.?|.[^a]?.?|..?[^t]? )$

Lors de la troisième tentative, les deuxième et troisième lettres ont été rendues facultatives pour permettre la correspondance d'extensions inférieures à trois caractères, telles que "sendmail. cf".


Le motif est désormais très complexe, ce qui le rend difficile à lire. Pire encore, si le problème change et que vous souhaitez des extensions autres que « bat » et « exe », le modèle devient encore plus compliqué et déroutant.


Transférer les clips de négation tout cela vers :

.*[.](?!bat$).* $

Sens direct : si l'expression bat ne correspond pas ici, essayez le reste du modèle ; si bat$ correspond, le modèle entier échouera. Le $ de fin est requis pour garantir que les extensions commençant par « bat » comme « sample.batch » sont autorisées.


Il est désormais facile d'exclure une autre extension de fichier ; il suffit de la rendre facultative dans le délimiteur. Le modèle ci-dessous exclura les noms de fichiers se terminant par « bat » ou « exe ».

. *[.](?!bat$|exe$).*$

Modifier la chaîne

Jusqu'à présent, nous avons simplement recherché une chaîne statique. Les expressions régulières sont également généralement utilisées de différentes manières pour modifier des chaînes via la méthode `RegexObject` ci-dessous.

方法/属性 作用
split() 将字符串在 RE 匹配的地方分片并生成一个列表,
sub() 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换
subn() 与 sub() 相同,但返回新的字符串和替换次数

Diviser la chaîne

La méthode split() de `RegexObject` divise la chaîne là où RE correspond et renverra une liste. Elle est similaire à la méthode string split() mais fournit plus de délimiteurs ; split() ne prend en charge que les espaces et les chaînes fixes. Comme vous vous en doutez, il existe également une fonction re.split() au niveau du module.

split(string [ , maxsplit = 0])

Divisez la chaîne via des expressions régulières. Si des crochets de capture sont utilisés dans un RE, leur contenu est également renvoyé dans le cadre de la liste des résultats. Si maxsplit est différent de zéro, alors au plus les fragments maxsplit peuvent être divisés.


Vous pouvez limiter le nombre de fractionnements en définissant la valeur maxsplit. Lorsque maxsplit est différent de zéro, il peut y avoir au maximum des divisions maxsplit et le reste de la chaîne est renvoyé comme dernière partie de la liste. Dans les exemples suivants, le délimiteur peut être n'importe quelle séquence de caractères non alphanumériques.

# !python

>>> p = re.compile(r'"W+')

> >> p.split('Ceci est un test, court et doux, de split().')

[
'Ceci'' est''un''test''court''et''doux ''de''divisé ''']

>>>  p.split('Ceci est un test, court et doux, de split().'3)

[
'Ceci' 'est''un''test, court et doux, de split().']

有时,你不仅对定界符之间的文本感兴趣,也需要知道定界符是什么。如果捕获括号在 RE 中使用,那么它们的值也会当作列表的一部分返回。比较下面的调用:

# !python

>>> p = re.compile(r'"W+')

> >> p2 = re.compile(r'("W+)')

>>> p.split('Ceci est un test.')

[
'Ceci ''est''un ''test''' ]

>>> p2.split('Ceci est un test.')

[
'Ceci'' ''est'' '' a'' ''test''.''']

模块级函数 re.split() et RE 作为第一个参数,其他一样。

# !python

>>> re.split('["W]+''Des mots, des mots, des mots.' )

[
'Mots''mots''mots''']

>>> re.split('(["W]+)''Des mots, des mots, des mots. ')

[
'Mots'' ''mots''''mots''.''']

>>> re.split('["W]+ ''Des mots, des mots, des mots.'1)

[
'Mots'' des mots, des mots.']

搜索和替换

其他常见的用途就是找到所有模式匹配的字符串并用不同的字符串来替换它们.sub() 方法提供一个替换值,可以是字符串或一个函数,和一个要被处理的字符串。

sub(replacement, string[, count =  0])

La chaîne renvoyée est remplacée par la correspondance non répétitive la plus à gauche de RE dans la chaîne. Si le modèle n'est pas trouvé, le caractère sera renvoyé inchangé.


Le nombre de paramètres facultatifs est le nombre maximum de substitutions après la correspondance de modèles ; le nombre doit être un entier non négatif. La valeur par défaut est 0 qui remplace toutes les correspondances.


Voici un exemple simple utilisant la méthode sub(). Il remplace le nom de la couleur par le mot « couleur ».

# !python

>>> p = re.compile( '(bleu|blanc|rouge)')

>>> p.sub( 'couleur', 'chaussettes bleues et chaussures rouges')

' chaussettes de couleur et chaussures de couleur'

>>> p.sub( 'couleur', 'chaussettes bleues et chaussures rouges', comptez=1)

'chaussettes de couleur et red shoes'

subn() a le même effet, mais renvoie un double tuple contenant la nouvelle chaîne et le nombre d'exécutions de remplacement.

# !python

>>> p = re.compile( '(bleu|blanc|rouge)')

>>> p.subn( 'couleur', 'chaussettes bleues et chaussures rouges')

(
'chaussettes de couleur et chaussures de couleur', 2)

>>> p.subn( 'couleur', ' pas de couleurs du tout')

(
'pas de couleurs du tout', 0)

Les matchs vides ne seront remplacés que s'ils ne suivent pas immédiatement un match précédent.

# !python

>>> p = re.compile('x*')

>> 'abxd')'-a-b-d- '

Si le remplacement est une chaîne, toutes les barres obliques inverses qu'elle contient seront traitées. ""n" sera converti en caractère de nouvelle ligne, ""r" en retour chariot, etc. Les échappements inconnus tels que ""j" sont laissés intacts. Les références arrière, telles que ""6", correspondent au groupe correspondant dans le RE et sont remplacées par la sous-chaîne. Cela vous permet d'insérer une partie du texte original dans la chaîne remplacée.
Cet exemple fait correspondre le mot "section" entouré de "{" et "}", et remplace "section" par "sous-section".

# !python

>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)

>>> p.sub(r'sous-section{"1} ','section{Première} section{seconde}')

'sous-section{Première} sous-section{seconde}'

peut également être spécifiée en utilisant (?P ..) définit un groupe nommé. ""g" correspondra à la sous-chaîne par le nom du groupe "name", et ""g" utilise le numéro de groupe correspondant ""2. ", mais la signification peut ne pas être claire dans la chaîne de remplacement, telle que ""g<2>0". (""20" est interprété comme une référence au groupe 20, et non au groupe 2 suivi d'une lettre "0".)

# !python

>>> p = re.compile('section{ (?P [^}]* ) }', re. VERBEUX)

>>> p.sub(r'sous-section{"1}','section{Première}')

'sous-section{Premier>'

>>> p.sub(r'subsection{"g<1>}', 'section{Première>')

'sous-section{Première}'

>>> p.sub(r' sous-section{"g}','section{Première}')

'sous-section{Première}'
替换也可以是一个甚至给你更多控制的函数。如果替换是个函数,该函数将会被模式中每Il s'agit de `MatchObject ` 的匹配函属,并可以使用这个信息去计算预期的字符串并返回它。

在下面的例子里,替换函数将十进制翻译成十六进制:

# !python

>>> def hexrepl( match ):

     
"Renvoyer la chaîne hexadécimale pour un nombre décimal"

     valeur 
= int( match.group() )

     
retour hex(valeur)



>>> p =  re.compile(r'"d+')

> ;>> p.sub(hexrepl, 'Appelez 65490 pour l'impression, 49152 pour le code utilisateur.' )

'Appelez 0xffd2 pour l'impression, 0xc000 pour le code utilisateur.'

当使用模块级的 re.sub() 一个字符串或一个 `Regex Object`;如果你需要指定正则表达式标志,你Si `RegexObject` est utilisé, le sub("(?i)b+", "x", "bbbb BBBB") renvoie 'x x'。

常见问题

正则表达式对一些应用程序来说是一个强大的工具,但在有些时候它并不直观而且有时它们不按你期望的运行。本节将指出一些最容易犯的常见错误。

使用字符串方式

有时使用 re 模块是个错误。如果你匹配一个固定的字符串或单个的字符类,并且你没有使用 re 的任何IGNORECASE 标志的功能,那么就没有必要使用正则表达式了。字符串有一些方法是对固定字符串进行操作的,它们通常快很多,因为都是一个个经过优化的C 小循环,用以代替举个用一个固定字符串替换另一个的例子;如,你可以把 "acte" 替换成 "mot"。re .sub() semble être la fonction à utiliser pour cela, mais considérez la méthode replace(). Il s'agit de replace() pour remplacer "espadon" et "sdeedfish", pour RE 也是可以做到的.换单词的一部分,模式将写成 "bword"b,这是为了要求 "mot" 两边有一个单词边界。另一个常见任务是从一个字符串中删除单个字符或用另一个字符来替代它。 Il s'agit de re.sub('"n',' ',S) qui est utilisé pour traduire() et de traduire().作起来更快。


总之,在使用 re 模块之前,先考虑一下你的问题是否可以用更快、更简单的字符串方法来解决。

La fonction

match() vs search()

match() vérifie uniquement si RE correspond au début de la chaîne, tandis que search() analyse la chaîne entière. Il est important de se rappeler cette distinction. N'oubliez pas que match() ne signale qu'une correspondance réussie, qui commence à 0 ; si la correspondance ne commence pas à 0, match() ne la signalera pas.

# !python

>>> imprimer re.match('super', 'superstition ').span()

(0,
5)

>>> imprimer re.match('super', 'insurmontable')

Aucun

search(), d'autre part, analysera la chaîne entière et signalera la première correspondance trouvée.

# !python

>>> imprimer re.search('super', 'superstition ').span()

(0,
5)

>>> imprimer re.search('super', 'insurmontable').span()

(
2, 7)

Parfois, vous pouvez être enclin à utiliser re.match(), uniquement si Ajoutez .* à la partie avant de RE. Veuillez essayer de ne pas faire cela et utilisez plutôt re.search(). Le compilateur d'expressions régulières effectue des analyses sur les RE pour accélérer le traitement lors de la recherche de correspondances. Un de ces analyseurs indiquera quel est le premier caractère de la correspondance ; par exemple, le modèle Crow doit correspondre en commençant par "C". L'analyseur permet au moteur d'analyser rapidement la chaîne pour trouver le caractère de départ, et de ne commencer à faire correspondre qu'après avoir trouvé "C".

L'ajout de .* entraînera l'échec de cette optimisation, ce qui nécessitera une analyse jusqu'à la fin de la chaîne, puis un retour en arrière pour trouver une correspondance pour le reste du RE. Utilisez plutôt re.search().

Greedy vs Not Greedy

Lorsqu'une expression régulière est répétée, comme avec un*, le résultat de l'opération est de faire correspondre autant de modèles que possible. Ce fait vous dérange souvent lorsque vous essayez de faire correspondre une paire symétrique de délimiteurs, tels que les crochets angulaires dans le balisage HTML. Les modèles correspondant à une seule balise HTML ne fonctionnent pas correctement en raison de la nature « gourmande » de .*

#!python

> ;>> s = ' Titre'

>>> len(s)

32

>>> imprimer re.match('<.*>', s).span()

(0,
32)

>>> imprimer re.match('<.*>', s).group()

<html><tête><titre>Titretitre>

RE correspond à "<" dans "<span style="font-family:新宋体"><html><code><span style="font-family:新宋体"><html></span>", * Consommer. la partie restante de la sous-chaîne. En gardant plus à gauche dans le RE, bien que > ne puisse pas correspondre à la fin de la chaîne, l'expression régulière doit donc revenir en arrière caractère par caractère jusqu'à ce qu'elle trouve une correspondance pour >. La correspondance finale va de "<" dans "" dans "", ce qui n'est pas ce que vous souhaitez.


Dans ce cas, la solution est d'utiliser des qualificatifs non gourmands *?, +?, ?? ou {m,n}? pour faire correspondre un texte le plus petit possible. Dans l'exemple ci-dessus, ">" est essayé immédiatement après le premier "<", et en cas d'échec, le moteur incrémente un caractère à la fois et réessaye ">" à chaque étape. Ce traitement obtiendra le résultat correct :

#!python

pat
= re .compile(r"""

"s*                           # Sauter les espaces de début

(?P

[^: ]+) # Nom de l'en-tête

"s* :                                                                                                                                          >
# perdre l'espace final suivant

"s*$                                                                                   Espaces de fin jusqu'à la fin de la ligne 



"""
, re.VERBOSE)Celui-ci est beaucoup plus difficile à lire :

Surlignage de code produit par Actipro CodeHighlighter (gratuit)

http://www .CodeHighlighter.com/
#

!python
pat
=
re.compile(r""s*(?P <en-tête>[^ :]+)"s*:(?P.*?)"s* $")Commentaires

Les expressions régulières sont un sujet complexe. Cet article peut-il vous aider à comprendre ? Ces parties ne sont-elles pas claires ou les problèmes que vous rencontrez ne sont-ils pas trouvés ici ? Si tel est le cas, veuillez envoyer des suggestions à l'auteur pour des améliorations.

Le livre le plus complet décrivant les expressions régulières est "Mastering Regular Expressions" écrit par Jeffrey Friedl, publié par O'Reilly. Malheureusement, ce livre se concentre uniquement sur les expressions régulières de style Perl et Java et ne contient aucun matériel Python, il n'est donc pas suffisant comme référence pour la programmation Python. (La première version incluait le module regex désormais obsolète de Python, qui est naturellement de peu d'utilité).

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn