2009-10-16 4 views
3

Je comprends queComment utiliser? et?: et: dans REGEX pour Python?

* = "zero or more" 
? = "zero or more" ...what's the difference? 

Aussi,: < < mon livre utilise, il dit son une « subtilité », mais je ne sais pas ce qu'ils font exactement!

+0

vous semblez avoir du mal à trouver ** tout ** tutoriel. Avez-vous besoin d'aide avec les moteurs de recherche? – SilentGhost

Répondre

5

C'est le même que {0,1}. Par ?:, vous signifiez probablement (?:X), où X est une autre chaîne. C'est ce qu'on appelle un "groupe non-capturant". Normalement, lorsque vous entourez une parenthèse, vous groupez ce qui correspond à ces parenthèses. Par exemple, l'expression régulière .(.).(.) correspond à 4 caractères (sauf les sauts de ligne) et stocke le deuxième caractère du groupe 1 et le quatrième caractère du groupe 2. Cependant, lorsque vous faites: .(?:.).(.) seul le quatrième caractère est stocké dans le groupe 1, tout (?:.) est apparié, mais pas "mémorisé".

Une petite démo:

import re 
m = re.search('.(.).(.)', '1234') 
print m.group(1) 
print m.group(2) 
# output: 
# 2 
# 4 

m = re.search('.(?:.).(.)', '1234') 
print m.group(1) 
# output: 
# 4 

Vous pourriez vous demander: "pourquoi utiliser ce groupe non-capture du tout?". Eh bien, parfois, vous voulez faire un OU entre deux chaînes, par exemple, vous voulez faire correspondre la chaîne "www.google.com" ou "www.yahoo.com", vous pouvez alors faire: www\.google\.com|www\.yahoo\.com, mais plus courte serait : www\.(google|yahoo)\.com bien sûr. Mais si vous ne faites pas quelque chose d'utile avec ce qui est capturé par ce groupe (la chaîne "google", ou "yahoo"), vous pouvez également utiliser un groupe non-capturant: www\.(?:google|yahoo)\.com. Lorsque le moteur regex n'a pas besoin de "se souvenir" de la sous-chaîne "google" ou "yahoo", votre application/script s'exécutera plus rapidement. Bien sûr, cela ne ferait pas beaucoup de différence avec des chaînes relativement petites, mais quand votre regex et votre chaîne augmenteront, cela le fera probablement.

Et pour un meilleur exemple d'utilisation de groupes non-capturants, voir le commentaire de Chris Lutz ci-dessous.

+2

Ce n'est pas seulement pour courir plus vite. Considérez ceci: '/ (\ w +)? \ S + (\ w +) /' Il peut y avoir un groupe ou deux groupes, et nous ne savons pas lequel est qui sans vérifier si le second existe ou non. Si nous savons que nous n'avons pas besoin du premier groupe (nous nous assurons simplement qu'il existe), nous pouvons utiliser '/ (?: \ W +)? \ S + (\ w +) /' et nous connaissons les données want est toujours dans le groupe 1. (Remplacer '\ w +' et '\ s +' par des expressions rationnelles plus compliquées pour obtenir un exemple concret plausible.) –

+0

Excellent point Chris! –

2

? = Zéro ou un

que vous utilisez (? :) pour le groupement w/o enregistrement du groupe dans une variable temporaire comme vous le feriez avec()

1

? ne signifie pas « zéro ou plus », cela signifie « zéro ou un".

4

: < < mon livre utilise, il dit son une « subtilité », mais je ne sais pas ce qu'ils font exactement!

Si c'est bien ce que votre livre dit, alors je vous conseille d'obtenir un meilleur livre.

Entre parenthèses (plus précisément: juste après une parenthèse ouvrante), ? a une autre signification. Il démarre un groupe de options qui ne comptent que pour la portée des parenthèses. ?: est un cas particulier de ces options. Pour comprendre ce cas particulier, vous devez d'abord savoir que les parenthèses créer des groupes de capture:

a(.)c 

C'est une expression régulière qui correspond à une chaîne de trois lettres commençant par a et se terminant par c. Le personnage du milieu est (plus ou moins) aribtraire. Puisque vous mettez entre parenthèses, vous pouvez capture il:

m = re.search('a(.)c', 'abcdef') 
print m.group(1) 

Cette imprimerez b, depuis m.group(1) capture le contenu des premières parenthèses (group(0) capture le coup, ici abc).

Maintenant, considérons cette expression régulière:

a(?:.)c 

Aucune capture est faite ici - c'est ce que ?: après une parenthèse signifie d'ouverture. C'est-à-dire que le code suivant échouera:

print m.group(1) 

Parce qu'il n'y a pas de groupe 1! Comme Manu l'a déjà dit, ? signifie "zéro ou une fois"