9
votes

Pourquoi mon regex avec r'string 'matchs mais pas "chaîne" en utilisant python?

La manière dont la réégalité fonctionne dans Python est si extrêmement perplexe que cela me rend plus furieux avec chaque seconde qui passe. Voici mon problème:

Je comprends que cela donne un résultat: p> xxx pré>

tandis que cela ne fait pas: p>

regex = '|'.join(['\b' + str(state) + '\b' for state in states])


1 commentaires

Remarque: les supports carrés sont redondants (en fait, nuisibles: la différence entre O (n) et O (1) consommation de mémoire), utilisez un Expression génératrice à la place.


4 Réponses :


4
votes

La solution est celle que vous avez utilisée dans l'exemple ci-dessus: chaînes brutes.

regex = '|'.join(r'\b' + str(state) + r'\b' for state in states)


5 commentaires

Pourquoi le besoin de cordes crues cependant?


Just \ b dans une chaîne est interprété comme une séquence d'évacuation et produit un code de contrôle de la cloche (je pense). Lorsque vous souhaitez que la regex (résultante) inclure une séquence d'évacuation toutefois, vous devez donc vous assurer que toute la séquence est incluse dans la chaîne. Vous devez donc échapper à la barre oblique inverse, séparément: \\ b qui donne dans un \ b dans la chaîne.


@ CHAR8705: Ajout d'une raison de cela dans ma réponse.


@Poke: \ b en tant que chaîne Escape est \ x08 , un code de contrôle BS (retour arrière), pas '\ x07` un-l bel. L'évasion pour Bel est \ a ... A comme dans "alerte", iirc. Voir EN.Wikipedia.org/wiki/Control_Character


@John Machin: Ouais, merci ^^ Mais je doute que je me souvienne de ça pour la prochaine fois ... (Eh bien, pourquoi devrais-je ?: P)



14
votes

l'anwser elle-même strong> xxx pré>

La raison derrière ceci est que le préfixe "R" indique à Python de ne pas analyser la chaîne que vous y passez. Si vous ne mettez pas de «R» avant la chaîne, Python essaiera de transformer tout type précédent par «\ 'dans un caractère spécial, pour vous permettre d'entrer des lignes de pause (\ N), des onglets (\ T) et de tels facilement. p>

Lorsque vous faites '\ b' code>, vous dites à Python de créer une chaîne, d'analyser et de transformer '\ b' en "backspace", alors que lorsque vous le faites R '\ B' Code>, Python stocke simplement '\' Alors 'B', et c'est ce que vous voulez avec pour regex. utilisez toujours "R 'pour la chaîne utilisée comme motifs de regex. em> p>

La notation" R "est appelée" chaîne brute ", mais c'est trompeur, comme il n'y a pas de telle chose qu'une Chaîne brute dans les internes Python. Pensez simplement à cela comme moyen de dire à Python d'éviter d'être trop intelligent. P>

Il y a une autre notation dans Python u'string code> ', qui dit à Python de stocker le chaîne comme unicode. Vous pouvez combiner les deux: ur "à © © \ n" code> stockera "\ bà ©" comme unicode, tandis que u "à © ¡n" code> stockera "© ©" Puis une pause de ligne. P>

Quelqu'un moyen d'améliorer votre code: strong> p> xxx pré>

supprimé le supplément [] code>. Il dit à Python de ne pas stocker dans la mémoire la liste des valeurs que vous générez. Nous pouvons le faire ici car nous ne prévoyons pas de réutiliser la liste que vous créez puisque vous l'utilisez directement dans votre joindre () code> et nulle part ailleurs. P>

matches = [s for s in states if s in 'grand rapids, mi 49505']


2 commentaires

Bon sang. Attends, je pourrais être italien!


Juste un mot complémentaire. Le [] peut être supprimé car (r '\ b' + str (état) + r '\ b' pour l'état dans les états) renvoie un < Tapez 'Générateur'> , qui peut être itéré par fonction suivant et accepté comme argument de '' .join (). Donc, il n'est pas nécessaire de construire une liste de cette itératrice.



2
votes

La clé est de comprendre la différence entre '\ B' et R '\ B'. Taper ceux-ci dans les résultats inactifs dans cette sortie:

>>> '\b'
'\x08'
>>> r'\b'
'\\b'


1 commentaires

C'est trompeur. Python ne stocke pas r '\ b' comme "\\ b" en interne. C'est inactif et la plupart des coquillages Python qui l'affichent de cette façon de vous donner un indice de ce qui est à l'intérieur. Mais vous n'obtiendrez pas la même chose si vous imprimez. Cela va confondre tous les débutants.



0
votes

briser ces deux chaînes vers le bas:

import re

pattern = re.compile(r'''
    (?ix) # ignore case, verbose
    \b    # word break
    (     # begin group 1
    AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|
    HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|
    MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|
    NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|
    SD|TN|TX|UT|VT|VA|WA|WV|WI|WY
    )     # end group 1
    \b    # word break
    ''')

m = pattern.search('Grand Rapids, MI 49505')
if m:
    print m.group(1)


1 commentaires

"Depuis que Pythonistas fronçons généralement des frigeurs ..." intéressant. Comment venir? Que voudriez-vous utiliser à la place?