2010-07-02 7 views
8

Supposons qu'il y ait deux cordes:python regex: correspondre à une chaîne avec une seule instance d'un caractère

$1 off delicious ham. 
$1 off delicious $5 ham. 

En Python, puis-je avoir une expression régulière qui correspond quand il n'y a qu'un seul $ dans la chaîne? Par exemple, je veux que le RE corresponde à la première phrase, mais pas à la seconde. J'ai essayé quelque chose comme:

re.search(r"\$[0-9]+.*!(\$)","$1 off delicious $5 ham.") 

..saying « match où vous voyez un $ suivi de tout, sauf pour un autre $. » Il n'y avait pas de correspondance sur l'exemple $$, mais il n'y avait pas de correspondance sur l'exemple $.

Merci d'avance!

méthode de test simple pour vérifier:

def test(r): 
    s = ("$1 off $5 delicious ham","$1 off any delicious ham")  
    for x in s: 
    print x 
    print re.search(r,x,re.I) 
    print "" 
+2

pourquoi ne pas utiliser la méthode '.count()' des cordes? –

+0

Je suis en train de saboter un RE dans un outil qui ne me laisse pas ajouter de logique supplémentaire. Donc je ne peux pas faire "si count (str," $ ")> 1: passer". J'ai besoin de re pour ne pas correspondre sur une telle chaîne. – Chris

Répondre

11
>>> import re 
>>> onedollar = re.compile(r'^[^\$]*\$[^\$]*$') 
>>> onedollar.match('$1 off delicious ham.') 
<_sre.SRE_Match object at 0x7fe253c9c4a8> 
>>> onedollar.match('$1 off delicious $5 ham.') 
>>> 

Répartition des regexp:
^ ancre au début de la chaîne
[^\$]* zéro ou plusieurs caractères qui ne sont pas $
\$ match un signe dollar
[^\$]* Zéro ou plusieurs caractères qui ne sont pas $
$ ancre à la fin de chaîne

+0

Points bonus pour le show-n-tell. Avez-vous quelques minutes pour me décrire ce qui se passe, ici? – Chris

+0

0 ou plus signe non dollar suivi d'un dollar suivi de 0 ou plus signe non dollar –

+0

Très utile en effet; Merci. – Chris

1
re.search("^[^$]*\$[^$]*$",test_string) 
1
^.*?\$[^$]*$ 

cela devrait faire l'affaire

+0

belle utilisation d'un match non-gourmand –

+0

Hmm ..N'a pas réussi le test, cependant, à moins qu'il y ait quelques drapeaux spéciaux dont j'ai besoin:

 >>> test(r"^.*?\$[^$]*$") $1 off $5 delicious ham <_sre.SRE_Match object at 0x00ED6288> $1 off any delicious ham <_sre.SRE_Match object at 0x00ED6288> 
Chris

2

Vous voulez utiliser le complément d'une classe de caractères [^] pour correspondre à un caractère autre que $:

re.match(r"\$[0-9]+[^\$]*$","$1 off delicious $5 ham.") 

Les changements de l'original sont les suivantes:

  1. .* remplacé par [^\$]*. Le nouveau terme [^\$] signifie tout caractère autre que $
  2. $ ajouté à la chaîne. Force la correspondance à s'étendre jusqu'à la fin de la chaîne.
  3. re.search remplacé par re.match. Correspond à la chaîne entière, plutôt qu'à un sous-ensemble de celle-ci.
+0

N'a pas réussi! >>> test (r "$ \ [0-9] + [^ $ \] * $") 1 $ de rabais sur 5 délicieux jambon $ <_sre.SRE_Match objet à 0x00ED65D0> 1 $ sur tout délicieux jambon < _sre.SRE_Match objet à 0x00ED65D0> – Chris

8
>>> '$1 off delicious $5 ham.'.count('$') 
2 
>>> '$1 off delicious ham.'.count('$') 
1 
+1

Je suis d'accord, une expression régulière serait trop lourde ici. – Duncan

Questions connexes