2010-07-02 24 views
8

Supongamos que hay dos cadenas:pitón de expresiones regulares: coincidir con una cadena con una sola instancia de un personaje

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

En Python, puedo tener una expresión regular que coincide cuando sólo hay un $ en la cadena? Es decir, quiero que el RE coincida con la primera frase, pero no con la segunda. He intentado algo así como:

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

..saying "Match donde se ve una $ seguido de nada, excepto para otro $." No hubo coincidencia en el ejemplo $$, pero tampoco hubo coincidencia en el $ example.

¡Gracias de antemano!

método de prueba simple para la comprobación:

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

¿por qué no utilizar el método '.count()' de las cadenas? –

+0

Estoy utilizando un RE para convertirme en una herramienta que no me permite agregar ninguna lógica adicional. Entonces no puedo hacer "if count (str," $ ")> 1: pass". Necesito que no coincidan en una cadena así. – Chris

Respuesta

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.') 
>>> 

Desglose de expresión regular:
^ de anclaje al inicio de la cadena
[^\$]* Cero o más caracteres que no son $
\$ de ajuste de un signo de dólar
[^\$]* Cero o más caracteres que no son $
$ ancla al final de la cadena

+0

Puntos de bonificación para el show-n-tell. ¿Tienes un par de minutos para describirme qué está pasando aquí? – Chris

+0

0 o más letreros no dólares seguidos de un dólar seguido de 0 o más letreros que no sean dólares –

+0

Muy útil; Gracias. – Chris

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

esto debería hacer el truco

+0

buen uso de un partido no codicioso –

+0

Hmm ..No pasó la prueba, sin embargo, a menos que haya algunas banderas especiales que necesito:

 >>> 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

Usted desea utilizar el complemento de una clase de caracteres [^] para que coincida con cualquier carácter que no sea $:

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

Los cambios de la original son las siguientes:

  1. .* reemplazado con [^\$]*. El nuevo término [^\$] significa cualquier carácter que no sea $
  2. $ anexado a la cadena. Fuerza a que la coincidencia se extienda hasta el final de la cadena.
  3. re.search reemplazado por re.match. Coincide con toda la cadena, en lugar de cualquier subconjunto de la misma.
+0

¡No pasó! >>> prueba (r "\ $ [0-9] + [^ \ $] * $") $ 1 de descuento $ 5 delicioso jamón <_sre.SRE_Match objeto en 0x00ED65D0> $ 1 de descuento en cualquier delicioso jamón < _sre.SRE_Match objeto en 0x00ED65D0> – Chris

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

Acepto, una expresión regular sería exagerada aquí. – Duncan

Cuestiones relacionadas