El tokenizer de expresión regular de NLTK no está jugando bien con el punto decimal en la expresión regular

Estoy tratando de escribir un texto normalizador, y uno de los casos básicos que deben manejarse es convertir algo así como 3.14 a three point one four o three point fourteen .

Actualmente estoy usando el patrón \$?\d+(\.\d+)?%? con nltk.regexp_tokenize , que creo que debería manejar tanto los números como la moneda y los porcentajes. Sin embargo, en este momento, algo como $23.50 se maneja perfectamente (se analiza a ['$23.50'] ), pero 3.14 se analiza a ['3', '14'] – el punto decimal se está cayendo.

He intentado agregar un patrón separado \d+.\d+ a mi expresión regular, pero eso no ayudó (¿no debería mi patrón actual coincidir con eso?)

Edición 2 : También acabo de descubrir que la parte % tampoco parece funcionar correctamente: el 20% solo devuelve ['20'] . Siento que debe haber algún problema con mi expresión regular, pero lo he probado en Pythex y me parece bien.

Edición : Aquí está mi código.

 import nltk import re pattern = r'''(?x) # set flag to allow verbose regexps ([AZ]\.)+ # abbreviations, eg USA | \w+([-']\w+)* # words w/ optional internal hyphens/apostrophe | \$?\d+(\.\d+)?%? # numbers, incl. currency and percentages | [+/\-@&*] # special characters with meanings ''' words = nltk.regexp_tokenize(line, pattern) words = [string.lower(w) for w in words] print words 

Aquí están algunas de mis cadenas de prueba:

 32188 2598473 26 letters from A to Z 3.14 is pi. <-- ['3', '14', 'is', 'pi'] My weight is about 68 kg, +/- 10 grams. Good muffins cost $3.88 in New York <-- ['good', 'muffins', 'cost', '$3.88', 'in', 'new', 'york'] 

El culpable es:

 \w+([-']\w+)* 

\w+ coincidirá con los números y ya que no hay . allí, solo igualará 3 en 3.14 . Mueve las opciones un poco para que \$?\d+(\.\d+)?%? es antes de la parte de expresiones regulares anterior (para que la coincidencia se intente primero en el formato de número):

 (?x)([AZ]\.)+|\$?\d+(\.\d+)?%?|\w+([-']\w+)*|[+/\-@&*] 

regex101 demo

O en forma expandida:

 pattern = r'''(?x) # set flag to allow verbose regexps ([AZ]\.)+ # abbreviations, eg USA | \$?\d+(\.\d+)?%? # numbers, incl. currency and percentages | \w+([-']\w+)* # words w/ optional internal hyphens/apostrophe | [+/\-@&*] # special characters with meanings ''' 

Prueba este regex:

 \b\$?\d+(\.\d+)?%?\b 

Rodeo la expresión regular inicial con los límites de palabras que coinciden: \b .