Qu'est-ce exactement qu'un "brut de la chaîne regex" et comment pouvez-vous l'utiliser?

à Partir de la documentation python sur regex concernant '' caractère:

la solution est d'utiliser la notation brute de chaîne de Python pour la notation régulière les modèles d'expression; backslashs ne sont pas manipulés d'une manière particulière dans une chaîne de caractères littérale préfixée par 'r'. Donc r"n" est une chaîne de deux caractères contenant '' et 'n' tandis que "n" est une chaîne de caractères contenant un saut de ligne. Habituellement, les patterns seront exprimés en Python code utilisant cette notation de chaîne brute.

Quelle est cette notation de chaîne brute? Si vous utilisez un format de chaîne brut, est-ce que cela signifie "*" est pris comme un caractère littéral plutôt qu'un indicateur zéro ou plus? Cela ne peut évidemment pas être juste, sinon regex perdrait complètement son pouvoir. Mais alors si c'est une chaîne brute, comment reconnaît-elle les caractères newline si "n" est littéralement une barre oblique et un <!--8?

Je ne sais pas suivre.

Modifier pour bounty:

j'essaie de comprendre comment une chaîne de caractères brute regex correspond aux nouvelles lignes, aux onglets et aux jeux de caractères, par exemple w pour les mots ou d pour les chiffres ou tout le reste, si les motifs de chaînes brutes ne reconnaissent pas les antislashes comme quoi que ce soit de plus que des caractères ordinaires. Je pourrais vraiment utiliser quelques bons exemples.

36
demandé sur Yyttsa 2012-10-13 11:42:51

5 réponses

la réponse de Zarkonnen répond à votre question, mais pas directement. Laissez-moi être plus direct, et voir si je peux attraper la prime de Zarkonnen.

vous trouverez peut-être cela plus facile à comprendre si vous arrêtez d'utiliser les Termes "raw string regex" et "raw string patterns". Ces termes combinent deux concepts distincts: les représentations d'une chaîne particulière dans le code source de Python, et quelle expression régulière cette chaîne représente.

En fait, c'est utile de les considérer comme deux langages de programmation différents, chacun avec leur propre syntaxe. Le langage Python a du code source qui, entre autres choses, construit des chaînes avec certains contenus, et appelle le système d'expression régulier. Le système d'expression régulière a du code source qui réside dans les objets string, et correspond à strings. Les deux langues utilisent backslash comme caractère d'évasion.

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

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

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

2 \n

La classique Python notation de chaîne de caractères "\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 newline. Python docs 2.4.1. Les littéraux de chaîne dire, "Le caractère backslash (\) est utilisé pour échapper les caractères qui ont une signification spéciale, comme un saut de ligne, la barre oblique inverse elle-même, ou le personnage de la 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 à deux caractères, nous devons utiliser un autre barre oblique inverse caractère à échapper à la signification particulière de l'original barre oblique inverse caractère:

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

2 \n

si vous souhaitez représenter des chaînes qui ont beaucoup barre oblique inverse les personnages en eux? Python docs 2.4.1. Les littéraux de chaîne continuer, "les littéraux de Chaîne peut éventuellement être précédé de la lettre" r " ou "R"; ces chaînes sont appelés chaînes brutes et utiliser des règles différentes pour interpréter les séquences d'échappement de backslash."Voici notre chaîne à 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 différentes de la chaîne, toutes donnant 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. Python docs, 7.2. re - opérations D'expression régulière dit, "expressions Régulières utiliser le caractère barre oblique inverse ('\') pour indiquer les formes spéciales ou de permettre à des caractères spéciaux pour être utilisé sans invoquer leur signification particulière. Ceci entre en conflit avec L'usage de Python du même caractère pour le même but dans les littérales string..."

si vous voulez un Python régulier objet d'expression qui correspond à un caractère newline, alors vous avez besoin d'une chaîne de 2 caractères, constituée du barre oblique inverse caractère suivi de n personnage. Les lignes de code suivantes définissent toutes prog à un objet d'expression régulière qui reconnaît un caractère newline:

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

Alors, pourquoi est-ce que " habituellement les patterns seront exprimés en code Python en utilisant cette notation de chaîne brute."? Parce que les expressions régulières sont les cordes statiques, qui sont commodément représentées comme des lettres de cordes. Et à partir des différentes notations littérales de chaîne disponibles, les chaînes brutes sont un choix commode, lorsque l'expression régulière inclut un barre oblique inverse personnage.

Questions

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

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

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

Q: Ce qui se passe à l'onglet et les caractères d'espace? : au niveau du langage Python, string s ne pas onglet et espace personnage. Il commence avec 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 du code source dans le langage d'expressions régulières, où elle signifie " match a string consisting of a whitespace character, a tab character, and the four characters Word.

Q: comment les faire correspondre si c'est traité comme un backlash-s et un Backlash-t? : peut-être le la question est plus claire si les mots "vous" et " qui " sont rendus plus spécifiques: comment le système d'expressions régulières s'accorde-t-il avec les expressions backlash-s et Backlash-t? Comme "tout caractère espace' et 'onglet caractère".

Q: ou si vous avez la chaîne de 3 caractères backslash-n-newline? : 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 brut plus chaîne conventionneller"\n" "\n", ou d'une autre manière. Le système d'expression régulier correspond à la chaîne de 3 caractères backslash-n-newline quand il trouve deuxretour à la ligne caractères.

N.B. tous les exemples et références de documents sont en python 2.7.

mise à Jour: a incorporé des clarifications des réponses de @Vladislav Zorov et @M. buettner, and from follow-up question of @Aerovistae.

50
répondu Jim DeLaHunt 2017-07-19 20:29:28

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

si vous utilisez une chaîne régulière et que vous passez dans un motif comme "\t" à L'analyseur RegEx, Python traduira ce littéral dans un tampon avec le octet tab (0x09).

si vous utilisez une chaîne brute et que vous passez dans un modèle comme R "\t " à L'analyseur RegEx, Python ne fait aucune interprétation, et il crée un tampon avec deux octets:'\', et "t". (0x5c, 0x74).

L'analyseur RegEx sait quoi faire avec la séquence '\t' -- elle correspond à celle d'un onglet. Il sait aussi quoi faire avec le caractère 0x09 -- qui correspond aussi à un onglet. Dans la plupart des cas, les résultats sont indiscernables.

donc la clé pour comprendre ce qui se passe est de reconnaître qu'il y a deux parsers qui sont employés ici. Le premier est L'analyseur Python, et il traduit votre chaîne de caractères littéral (ou brute) en séquence d'octets. Le second est l'analyseur d'expressions régulières de Python, et il convertit une séquence d'octets en une expression régulière compilée.

9
répondu Geoff Gerrietts 2012-12-13 15:00:07

vous semblez avoir du mal avec L'idée qu'un RegEx ne fait pas partie de Python, mais d'un langage de programmation différent avec son propre analyseur et compilateur. Les chaînes Raw vous aident à obtenir le "code source" D'un RegEx en toute sécurité à L'analyseur de RegEx, qui assignera ensuite un sens à des séquences de caractères comme \d,\w,\n, etc...

le problème existe parce que Python et RegExps utilisent \ comme caractère d'échappement, qui est, par 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à vous devez utiliser "\n" Dans RegExps). L'avantage est que vous n'avez pas besoin de faire la différence entre les chaînes brutes et non-brutes dans ces langues, ils ne vont pas tous les deux essayer de convertir le texte et de le découper, parce qu'ils réagissent à différentes séquences d'évasion.

3
répondu Vladislav Zorov 2012-12-12 17:58:46

le problème avec l'utilisation d'une chaîne normale pour écrire des regexes qui contiennent un \ c'est que vous finissez par avoir à écrire \ pour tout \. Donc, les littéraux de chaîne "stuff\things" et r"stuff\things" produisez la même chaîne. Cela devient particulièrement utile si vous voulez écrire une expression régulière qui correspond à des backslashs.

utilisant des chaînes normales, un regexp qui correspond à la chaîne \"\\"!

Pourquoi? Parce que nous devons échapper \ deux fois: une fois pour la syntaxe d'expression régulière, et une fois pour la syntaxe de la chaîne.

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

r'''stuff\
things'''

notez qu'habituellement, python traiterait \ - newline comme continuation de ligne, mais ce n'est pas le cas dans les chaînes brutes. Notez également que les antislashs échappent toujours aux guillemets dans les chaînes brutes, mais sont laissés en eux-mêmes. Donc la chaîne brute littéraler"\"" produit la chaîne \". Cela signifie que vous ne pouvez pas arrêter une corde crue littérale avec une barre oblique inverse.

Voir la section d'analyse lexicale de la documentation Python pour plus d'informations.

2
répondu Zarkonnen 2017-05-02 21:30:35

la section de manuel de Python pertinente ("String and Bytes literals") a une explication claire des lettres de chaîne brutes:

les caractères littéraux des chaînes et des octets peuvent être préfixés, en option, par un la lettre ' r 'ou' R'; de telles chaînes sont appelées chaînes brutes et treat les barres obliques inverses de caractères littéraux. En conséquence, dans string littérals, Les' \U 'et les' \u ' échappés en cordes brutes ne sont pas traités spécialement. Donné ce Python 2.les littérales brutes de X en unicode se comportent différemment de Python 3.la syntaxe 'ur' de x n'est pas supportée.

nouveau dans la version 3.3: le préfixe "rb" des octets bruts littéraux a été ajouté comme synonyme de "br".

nouveau dans la version 3.3: prise en charge de l'héritage littéral unicode (u'valeur') a été réintroduit pour simplifier le maintien de dual Python 2.x et 3.x code. Voir PEP 414 pour plus d'information.

dans les cordes à triple guillemet, les nouvelles lignes et les guillemets Non escamotés sont autorisés (et sont retenus), sauf que trois des citations sans détour mettre fin à la chaîne. (Une "citation" est le caractère utilisé pour ouvrir le chaîne, c'est à dire soit " ou ".)

a moins qu'un préfixe 'r' ou 'R' ne soit présent, les séquences d'échappement en chaîne sont interprétées selon des règles similaires à celles utilisées par Standard C. Les séquences d'évasion reconnues sont les suivantes:

Séquence D'Évasion Signification Notes

\newline Backslash et newline ignored

\ (Barre oblique inverse)

\' L'apostrophe (')

\" Guillemet Double (")

\a ASCII Bell (BEL)

\B ASCII Backspace (BS)

\F ASCII Formfeed (FF)

\ n ASCII Linefeed (LF)

\R ASCII Carriage Return (CR)

Tab. Horizontal (TAB.) \ V ASCII Vertical Tab (VT)

\ooo Caractère de valeur octale ooo (1,3)

\xhh Caractère, avec une valeur hexadécimale hh (2,3)

les séquences D'évasion seulement reconnues dans la littérature des cordes sont:

séquence D'évasion Signification Notes \n {Nom} caractère nom dans le nom Base de données Unicode (4) \ uxxxx caractère avec une valeur hex de 16 bits xxxx (5) \ Uxxxxxxxx caractère à valeur hexadécimale de 32 bits xxxxxxxx (6)

Notes:

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

  2. Contrairement à la Norme C, exactement deux chiffres hexadécimaux sont requis.

  3. En octets littérale, octales et hexadécimales échappe à désigner l'octet avec la valeur donnée. Dans une chaîne littérale, ces évasions dénotent 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 encodées en utilisant cette séquence d'échappement. Exactement quatre chiffres hexadécimaux sont requis.

  6. n'importe quel caractère Unicode peut être encodé de cette façon, mais les caractères en dehors du Plan multilingue de base (BMP) seront encodés en utilisant un si Python est compilé pour utiliser des unités de code 16 bits (la défaut.) Exactement huit chiffres hexadécimaux sont nécessaires.

contrairement à la norme C, toutes les séquences d'évasion non reconnues sont laissées dans le chaîne inchangé, c'est à dire, la barre oblique inverse est à gauche de la chaîne. (Ce comportement est utile lorsque débogage: si une séquence d'échappement est mal typée, la sortie résultante est plus facilement reconnue comme cassée. Il est également important de noter que les séquences d'échappement reconnus uniquement dans la chaîne de les littérales entrent dans la catégorie des échappées non reconnues pour les octets littéral.

même dans une chaîne brute, les guillemets de chaîne peuvent être échappés avec un antislash, mais l'antislash reste dans la chaîne; par exemple, r " \" est un valide chaîne littérale composée de deux caractères: un antislash et un double citation; r " \ " n'est pas une chaîne valide littérale (même une chaîne brute ne peut pas fin dans un nombre impair de backslashs). Plus précisément, une corde brute ne peut pas se terminer par un simple antislash (puisque le antislash citation suivante de caractères). Notez aussi qu'une seule barre oblique inverse suivie par une nouvelle ligne est interprété comme ces deux caractères comme faisant partie de la chaîne, non pas comme une continuation de ligne.

1
répondu Lorenzo Gatti 2012-12-14 16:05:34