2010-08-23 15 views
6

Soy un novato en las expresiones regulares, por lo que agradecería un poco de comentarios de los compañeros sobre este. Se usará mucho en mi sitio, por lo que cualquier caso de bordes extraños puede causar estragos. La idea es escribir una cantidad de un ingrediente en una receta en unidades enteras o fracciones. Debido a mi mecanismo de autocompletar, solo un número es válido también (ya que aparecerá un menú desplegable). Estas líneas son válidas:¿Alguna forma de mejorar esta expresión regular?

1 
1/2 
1 1/2 
4 cups 
4 1/2 cups 
10 3/4 cups sliced 

La parte numérica de la línea debe ser su propio grupo para que pueda analizar que con mi analizador fracción. Todo después de la parte numérica debe ser un segundo grupo. Al principio, he intentado esto:

^\s*(\d+|\d+\/\d+|\d+\s*\d+\/\d+)\s*(.*)$ 

Esto casi funciona, pero "1 1/2 tazas" se analiza como conseguir (1) (1/2 taza) en vez de (1 1/2) y (tazas) Después de rascarme un poco la cabeza, determiné que esto se debía al orden de mi cláusula "O". (1) satisface el \ d + y (. *) Satisface el resto. Así que cambié a este:

^\s*(\d+\/\d+|\d+\s*\d+\/\d+|\d+)\s*([a-z].*)$ 

Esto casi funciona, pero permite rarezas como "1 1/2/4 tazas" o "1/2 3 tazas". Así que decidí hacer cumplir una letra como primer carácter después de una expresión numérica válida:

^\s*(\d+\/\d+|\d+\s*\d+\/\d+|\d+)\s*($|[a-z].*)$ 

Nota estoy corriendo esta en el modo de mayúsculas y minúsculas. Aquí están mis preguntas:

  1. ¿Se puede mejorar la expresión? Me gusta un poco la lista "O" para el número, la fracción, la fracción compuesta, pero no se me ocurrió una forma de permitir números enteros, fracciones o fracciones compuestas.

  2. Sería muy agradable si pudiera devolver un grupo para cada palabra después del componente numérico. Como un grupo para (10 3/4), un grupo para (tazas) y un grupo para (rebanadas). Puede haber cualquier cantidad de palabras después. es posible?

Gracias!

+0

Oh uy, se perdió un caso más .. La cantidad puede expresarse en decimales. Así que agregué una cláusula O más: ^ \ s * (\ d + \/\ d + | \ d + \ s * \ d + \/\ d + | \ d + | \ d * \. \ D) \ s * ($ | [az]. *) $ –

Respuesta

3

Bueno, me parece que no necesita condiciones de quirófano en absoluto (pero consulte a continuación).

Para el bit numérico, que podría salirse con:

\d+(\s+\d+/\d+) 

que manejar todos esos valores fraccionarios.

Aún conservaría el decimal separado con una cláusula OR, ya que es probable que complique las cosas. Así que creo que probablemente podría salirse con algo como:

^\s*((\d+\s)?(\d+/\d+)?|\d+(\.\d+)?)\s*([a-z].*)?$ 
| |     |   | | 
| |     |   | +--- start of alpha section. 
| |     |   +------ optional white space. 
| |     +------------------ decimal (nn[.nn]) 
| +------------------------------------- fractional ([nn ][nn/nn]) 
+----------------------------------------- optional starting space. 

a pesar de que permite una cantidad fraccionaria vacío por lo que puede ser mejor con lo que tienes (entera, fraccionaria y decimal en separada cláusulas OR) .

prefiero el constructo ([a-z].*)?$ a ($|[a-z].*)$ mí mismo, sino que sólo puede ser una aversión en mi pasado para tener múltiples marcadores de fin de línea en mi RE :-)


Pero, honestamente, creo que se puede estar tratando de golpear una mosca con una ojiva termo-nuclear aquí.

¿Usted realmente necesita restringir lo que se ingresa. He visto recetas que requieren a pinch of salt y a handful of sultanas. Personalmente creo que puedes estar siendo restrictivo en lo que permitirás. Tendría un campo de forma libre para la cantidad y un menú desplegable para el tipo de comida (en realidad, probablemente solo permitiría la forma libre para el lote, a menos que ofreciera la posibilidad de buscar recetas basadas en lo que hay en la nevera).

+0

Tal vez estamos usando diferentes analizadores, pero eso no coincide con ninguno de mis ejemplos anteriores. Pero creo que veo lo que intenta hacer con el signo de interrogación. –

+0

@Mike, no estoy tan optimista con el motor de Javascript RE como me gustaría, pero esperaba que las partes descriptivas estuvieran entendiendo la idea. – paxdiablo

+0

Sí, mirando tu expresión, creo que debería funcionar también, pero por alguna razón, no :) Estoy usando RegExTester.com para probar cosas. –

1

Creo que esta expresión regular debe hacer lo que quiera:

/^\s*(\d+ \d+\/\d+|\d+\/\d+|\d+)\s*(.*)/ 

para hacer coincidir las palabras específicas que sólo debe hacer una división en el espacio en blanco después de que el análisis sintáctico. Hay algunas cosas que no desea hacer con expresiones regulares;)

+0

Sí que funciona, solo sin soporte decimal ... y cambié (. *) A ([az]. *) Para deshacerme de cosas como 1/2/cups .. –

+0

En realidad probablemente ($ | [az]. *) es aún mejor, ya que no quiero requerir nada después de la parte numérica. –

+0

Ah sí. Si desea soporte decimal que '[\ d.] +' Se debe usar en su lugar. Sin embargo, es difícil mantenerlo completamente contenido en una expresión regular si quieres agregar reglas complejas. – Wolph

Cuestiones relacionadas