84 votes

Qu'est-ce qu'une "raw string regex" et comment l'utiliser ?

D'après la documentation python sur expressions rationnelles concernant les '\' caractère :

La solution consiste à utiliser le logiciel Python Les barres obliques inverses ne sont pas gérées de manière particulière dans un littéral de chaîne préfixé par 'r' . Ainsi r"\n" est une chaîne de deux caractères contenant '\' y 'n' , tandis que "\n" i contenant une nouvelle ligne. En général, les motifs sont exprimés en code Python en utilisant cette notation de chaîne brute.

Qu'est-ce que la notation brute des chaînes de caractères ? Si vous utilisez un format de chaîne brute, cela signifie-t-il que "*" est considéré comme un caractère littéral plutôt que comme un indicateur zéro ou plus ? Ce n'est évidemment pas possible, sinon la regex perdrait toute sa puissance. Mais alors, s'il s'agit d'une chaîne de caractères brute, comment reconnaît-elle les caractères de retour à la ligne si "\n" est littéralement une barre oblique inverse et un "n" ?

Je ne suis pas.

Modifier pour la prime :

J'essaie de comprendre comment une regex de chaîne brute correspond aux nouvelles lignes, aux tabulations et aux jeux de caractères, par exemple. \w pour les mots ou \d pour les chiffres ou autres, si les modèles de chaînes brutes ne reconnaissent pas les barres obliques inverses comme étant plus que des caractères ordinaires. J'aurais vraiment besoin de bons exemples.

113voto

Jim DeLaHunt Points 3395

La réponse de Zarkonnen répond à votre question, mais pas directement. Je vais essayer d'être plus direct, et voir si je peux obtenir la prime de Zarkonnen.

Vous comprendrez peut-être plus facilement si vous cessez d'utiliser les termes "raw string regex" et "raw string patterns". Ces termes confondent deux concepts distincts : la représentation d'une chaîne particulière dans le code source Python et l'expression régulière que cette chaîne représente.

En fait, il est utile de les considérer comme deux langages de programmation différents, chacun ayant sa propre syntaxe. Le langage Python possède un code source qui, entre autres choses, construit des chaînes de caractères avec un certain contenu et appelle le système d'expressions régulières. Le système d'expressions régulières possède un code source qui réside dans des objets de type chaîne de caractères et qui fait correspondre des chaînes de caractères. Les deux langages utilisent la barre oblique inverse comme caractère d'échappement.

Tout d'abord, il faut comprendre qu'une chaîne de caractères est une séquence de caractères (c'est-à-dire des octets ou des points de code Unicode ; la distinction n'a pas beaucoup d'importance ici). Il existe de nombreuses façons de représenter une chaîne de caractères dans le code source Python. A chaîne brute est simplement l'une de ces représentations. Si deux représentations aboutissent à la même séquence de caractères, elles produisent un comportement équivalent.

Imaginez une chaîne de 2 caractères, composée de l'élément barre oblique inverse suivi du caractère n caractère. Si vous savez que la valeur du caractère pour barre oblique inverse est de 92, et pour n est 110, alors cette expression génère notre chaîne de caractères :

s = chr(92)+chr(110)
print len(s), s

2 \n

La notation conventionnelle des chaînes de caractères de Python "\n" ne génère pas cette chaîne. Au lieu de cela, il génère une chaîne d'un caractère avec un caractère de retour à la ligne. La chaîne Documentation Python 2.4.1. Caractères littéraux des chaînes de caractères dire : "La barre oblique inverse (\) est utilisée pour échapper à des caractères qui ont une signification spéciale, tels que la nouvelle ligne, la barre oblique inverse elle-même ou le caractère de citation".

s = "\n"
print len(s), s

1 
 

(Notez que la nouvelle ligne n'est pas visible dans cet exemple, mais si vous regardez attentivement, vous verrez une ligne vide après le "1").

Pour obtenir notre chaîne de deux caractères, nous devons utiliser un autre fichier barre oblique inverse pour échapper à la signification spéciale du caractère d'origine barre oblique inverse caractère :

s = "\\n"
print len(s), s

2 \n

Que faire si l'on veut représenter des chaînes de caractères qui ont plusieurs barre oblique inverse des personnages ? Documentation Python 2.4.1. Caractères littéraux des chaînes de caractères Les chaînes littérales peuvent éventuellement être préfixées par la lettre "r" ou "R" ; ces chaînes sont appelées "chaînes de caractères". chaînes brutes et utilisent des règles différentes pour interpréter les séquences d'échappement backslash". Voici notre chaîne de deux caractères, en utilisant la représentation brute de la chaîne :

s = r"\n"
print len(s), s

2 \n

Nous avons donc trois représentations de chaînes différentes, qui donnent toutes la même chaîne, ou séquence de caractères :

print chr(92)+chr(110) == "\\n" == r"\n"
True

Passons maintenant aux expressions régulières. Les expressions Python docs, 7.2. re - Opérations sur les expressions régulières dit : "Les expressions régulières utilisent la barre oblique inverse ('\') pour indiquer des formes spéciales ou pour permettre l'utilisation de caractères spéciaux sans invoquer leur signification particulière. Cela entre en conflit avec l'utilisation par Python du même caractère pour la même raison dans les chaînes de caractères littérales..."

Si vous voulez un objet d'expression régulière Python qui corresponde à un caractère de nouvelle ligne, vous avez besoin d'une chaîne de deux caractères, composée de l'expression suivante barre oblique inverse suivi du caractère n caractère. Les lignes de code suivantes définissent toutes prog à un objet d'expression régulière qui reconnaît un caractère de nouvelle ligne :

prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")

Comment se fait-il donc que "En général, les motifs sont exprimés dans le code Python à l'aide de cette notation de chaîne brute." ? Parce que les expressions régulières sont souvent des chaînes statiques, qui sont commodément représentées comme des chaînes littérales. Et parmi les différentes notations de chaînes littérales disponibles, les chaînes brutes sont un choix commode, lorsque l'expression rationnelle comprend un élément barre oblique inverse caractère.

Questions

Q : qu'en est-il de l'expression re.compile(r"\s\tWord") ? A : Il est plus facile de comprendre en séparant la chaîne de caractères de la compilation de l'expression régulière, et en les comprenant séparément.

s = r"\s\tWord"
prog = re.compile(s)

La chaîne s contient huit caractères : a barre oblique inverse , un s , a barre oblique inverse , a t puis quatre caractères Word .

Q : Qu'advient-il des tabulations et des espaces ? A : Au niveau du langage Python, les chaînes de caractères s n'a pas onglet y espace caractère. Il commence par quatre caractères : barre oblique inverse , s , barre oblique inverse , t . Le système d'expressions régulières, quant à lui, traite cette chaîne comme un code source dans le langage des expressions régulières, où il signifie "correspondre à une chaîne composée d'un caractère d'espacement, d'un caractère de tabulation et des quatre caractères Word .

Q : Comment faire correspondre ces deux éléments s'ils sont traités comme des backlash-s et backslash-t ? A : La question est peut-être plus claire si les mots "you" et "that" sont précisés : comment le système d'expressions régulières fait-il correspondre les expressions backlash-s et backslash-t ? En tant que "tout caractère d'espacement" et en tant que ' onglet caractère".

Q : Ou si vous avez la chaîne de 3 caractères backslash-n-newline ? A : Dans le langage Python, la chaîne de 3 caractères backslash-n-newline peut être représentée comme une chaîne conventionnelle "\\n\n" ou chaîne de caractères brute et conventionnelle r"\n" "\n" ou d'autres manières. Le système d'expressions régulières fait correspondre la chaîne de 3 caractères backslash-n-newline lorsqu'il trouve deux caractères consécutifs nouvelle ligne caractères.

N.B. Tous les exemples et toutes les références documentaires se rapportent à Python 2.7.

Mise à jour : Incorporation des clarifications des réponses de @Vladislav Zorov et @m.buettner, et de la question de suivi de @Aerovistae.

20voto

Geoff Gerrietts Points 576

La plupart de ces questions contiennent beaucoup de mots et il est peut-être difficile de trouver la réponse à votre question spécifique.

Si vous utilisez une chaîne de caractères régulière et que vous passez un motif comme " \t "à l'analyseur RegEx, Python traduira ce littéral en un tampon contenant l'octet de tabulation (0x09).

Si vous utilisez une chaîne brute et que vous passez un motif comme r" \t Dans le cas d'une requête de type " RegEx " à l'analyseur de RegEx, Python n'effectue aucune interprétation et crée un tampon contenant deux octets : '\' et 't' (0x5c, 0x74).

L'analyseur syntaxique RegEx sait ce qu'il faut faire de la séquence ' \t Il compare ces données à celles d'un onglet. Il sait également quoi faire du caractère 0x09 -- qui correspond également à une tabulation. Dans la plupart des cas, les résultats ne seront pas différenciés.

Pour comprendre ce qui se passe, il faut donc savoir que deux analyseurs sont utilisés. Le premier est l'analyseur Python, et il traduit votre littéral de chaîne (ou littéral de chaîne brut) en une séquence d'octets. Le second est l'analyseur d'expressions régulières de Python, qui convertit une séquence d'octets en une expression régulière compilée.

6voto

Zarkonnen Points 11086

Le problème lié à l'utilisation d'une chaîne de caractères normale pour écrire des expressions rationnelles contenant un élément \ est que vous finissez par devoir écrire \\ pour chaque \ . Ainsi, les chaînes de caractères littérales "stuff\\things" y r"stuff\things" produisent la même chaîne. Ceci est particulièrement utile si vous voulez écrire une expression régulière qui correspond aux barres obliques inverses.

En utilisant des chaînes normales, une expression rationnelle qui correspond à la chaîne \ serait "\\\\" !

Pourquoi ? Parce que nous devons nous échapper \ deux fois : une fois pour la syntaxe des expressions régulières et une fois pour la syntaxe des chaînes de caractères.

Vous pouvez utiliser des guillemets triples pour inclure des nouvelles lignes, comme ceci :

r'''stuff\
things'''

Notez qu'habituellement, python traite \ -comme une suite de ligne, mais ce n'est pas le cas dans les chaînes de caractères brutes. Notez également que les barres obliques inverses échappent toujours aux guillemets dans les chaînes brutes, mais qu'elles sont laissées en elles-mêmes. Ainsi, la chaîne brute littérale r"\"" produit la chaîne de caractères \" . Cela signifie que vous ne pouvez pas terminer un littéral de chaîne brute par une barre oblique inverse.

Véase la section d'analyse lexicale de la documentation Python pour plus d'informations.

4voto

Vladislav Zorov Points 1712

Vous semblez avoir du mal à comprendre qu'un RegEx ne fait pas partie de Python, mais qu'il s'agit d'un langage de programmation différent, avec son propre analyseur et son propre compilateur. Les chaînes brutes vous permettent de transmettre en toute sécurité le "code source" d'un RegEx à l'analyseur de RegEx, qui attribuera alors une signification aux séquences de caractères telles que \d , \w , \n etc.

Ce problème est dû au fait que Python et les RegExps utilisent la fonction \ comme caractère d'échappement, ce qui est d'ailleurs une coïncidence - il y a des langues avec d'autres caractères d'échappement (comme "`n" pour une nouvelle ligne, mais même là il faut utiliser " \n "dans RegExps). L'avantage est qu'il n'est pas nécessaire de faire la différence entre les chaînes brutes et les chaînes non brutes dans ces langages, qui n'essaieront pas de convertir le texte et de le massacrer, parce qu'ils réagissent à des séquences d'échappement différentes.

1voto

Lorenzo Gatti Points 493

La section correspondante du manuel Python ("String and Bytes literals") contient une explication claire des chaînes de caractères brutes :

Les chaînes de caractères et les octets littéraux peuvent éventuellement être préfixés par le signe lettre 'r' ou 'R' ; ces chaînes sont appelées chaînes brutes et traitent les comme des caractères littéraux. Par conséquent, dans les chaînes littérales, ' \U et \u ' dans les chaînes de caractères brutes ne sont pas traitées de manière particulière. Etant donné que la chaîne unicode brute de Python 2.x li 3.x, la syntaxe "ur" n'est pas prise en charge.

Nouveau dans la version 3.3 : Le préfixe 'rb' des littéraux d'octets bruts a été ajouté en tant que synonyme de 'rb'. a été ajouté en tant que synonyme de "br".

Nouveau dans la version 3.3 : La prise en charge de l'ancien littéral unicode (u'value') a été réintroduit pour simplifier la maintenance des bases de code Python 2.x et 3.x. Voir PEP 414 pour plus d'informations.

Dans les chaînes à triple guillemets, les nouvelles lignes et les guillemets non encapsulés sont autorisés (et sont conservés), sauf que trois guillemets non encapsulés d'affilée mettent fin à la chaîne. (Un "guillemet" est le caractère utilisé pour ouvrir la c'est-à-dire ' ou ".)

À moins qu'un préfixe "r" ou "R" ne soit présent, les séquences d'échappement dans les chaînes de caractères sont interprétées selon des règles similaires à celles utilisées par le standard C. Les séquences d'échappement reconnues sont les suivantes :

Séquence d'échappement Signification Notes

\newline Barre oblique inverse et nouvelle ligne ignorées
\ Barre oblique inversée ()
\' Guillemets simples (')
\" Double guillemet (")
\a ASCII Bell (BEL)
\b Espace arrière ASCII (BS)
\f ASCII Formfeed (FF)
\n Saut de ligne ASCII (LF)
\r Retour chariot ASCII (CR)
\t Tabulation horizontale ASCII ( \v Tabulation verticale ASCII (VT)
\ooo Caractère avec valeur octale ooo (1,3)
\xhh Caractère avec valeur hexagonale hh (2,3)

Les séquences d'échappement reconnues uniquement dans les chaînes de caractères littérales sont les suivantes :

Séquence d'échappement Signification Notes \N {nom} Nom du caractère nommé dans la base de données base de données Unicode (4) \uxxxx Caractère avec hexagone de 16 bits v \Uxxxxxxxx Caractère avec une valeur hexagonale de 32 bits xxxxxxxx (6)

Notes :

  1. Comme dans la norme C, jusqu'à trois chiffres octaux sont acceptés.

  2. Contrairement à la norme C, il faut exactement deux chiffres hexadécimaux.

  3. Dans un littéral d'octets, les caractères d'échappement hexadécimaux et octaux indiquent l'octet ayant la valeur donnée. Dans un littéral de chaîne de caractères, ces échappements indiquent une valeur de caractère Unicode avec la valeur donnée.

  4. Modifié dans la version 3.3 : La prise en charge des alias de noms [1] a été ajoutée.

  5. Les unités de code individuelles qui font partie d'une paire de substituts peuvent être codées à l'aide de cette séquence d'échappement. Quatre chiffres hexadécimaux exactement sont sont nécessaires.

  6. Tout caractère Unicode peut être encodé de cette manière, mais les caractères situés en dehors du plan multilingue de base si Python est compilé pour utiliser des unités de code 16 bits (par défaut). par défaut). Huit chiffres hexadécimaux exactement sont nécessaires.

Contrairement à la norme C, toutes les séquences d'échappement non reconnues sont laissées dans le champ inchangées, c'est-à-dire que la barre oblique inverse est laissée dans la chaîne. (Ce comportement comportement est utile lors du débogage : si une séquence d'échappement est mal saisie, la sortie résultante est plus facilement reconnue comme étant cassée). Il est également important de noter que les séquences d'échappement reconnues uniquement dans les chaînes de caractères tombent dans la catégorie des séquences d'échappement non reconnues pour les octets littérales.

Même dans une chaîne brute, les guillemets de chaîne peuvent être échappés par une barre oblique inverse, mais la barre oblique inverse reste dans la chaîne ; par exemple, r"\"" est une est un littéral de chaîne valide composé de deux caractères : une barre oblique inverse et un guillemet double ; r"\" n'est pas un littéral de chaîne valide. guillemets ; r"\" n'est pas un littéral de chaîne valide (même une chaîne brute ne peut se se terminer par un nombre impair de barres obliques inverses). Plus précisément, une chaîne brute ne peut pas se terminer par une seule barre oblique inverse (puisque la barre oblique inverse échapperait à la chaîne de caractères suivant). Notez également qu'une barre oblique inverse simple suivie suivie d'un saut de ligne est interprétée comme si ces deux caractères faisaient partie de la chaîne de caractères, et non comme un saut de ligne. et non comme un retour à la ligne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X