2012-02-29 14 views
11

Tengo un campo de entrada que es localizado. Necesito agregar una validación usando una expresión regular que debe tomar solo alfabetos y números. Podría haber usado [a-z0-9] si estuviera usando solo inglés.Regex para validar alfabéticos y números en la cadena localizada

A partir de ahora, estoy usando el método (sí, estoy iterando a través de cada carácter) para filtrar los alfabetos presentes en varios idiomas.

¿Hay alguna forma mejor de hacerlo? Cualquier regex u otras bibliotecas disponibles para esto?

+0

¿Quiere manejar también otros idiomas que no sean inglés, correcto? – Lukasz

+0

buscando una solución genérica ** que incluya inglés ** – ManuPK

+1

Según [esto] (http://stackoverflow.com/questions/2392194/how-to-match-the-international-alphabet-english-az-non-english -with-a-regu) publicar el '\ w' también funciona en expresiones regulares de perl en caracteres Unicode, no sé si esto es así en expresiones regulares java. – user1227804

Respuesta

18

Desde Java 7 puede utilizar Pattern.UNICODE_CHARACTER_CLASS

String s = "Müller"; 

Pattern p = Pattern.compile("^\\w+$", Pattern.UNICODE_CHARACTER_CLASS); 
Matcher m = p.matcher(s); 
if (m.find()) { 
    System.out.println(m.group()); 
} else { 
    System.out.println("not found"); 
} 

con la opción de que no reconocerá la palabra "Müller", pero utilizando Pattern.UNICODE_CHARACTER_CLASS

Habilita la versión Unicode de clases de personajes predefinidos y Clases de caracteres POSIX.

Ver here for more details

También puede echar un vistazo here for more Unicode information en Java 7.

y aquí en regular-expression.info una visión general sobre las propiedades Unicode scripts, y bloques.

See here a famous answer from tchrist acerca de las advertencias de expresiones regulares en Java, incluyendo una versión actualizada de lo que ha cambiado con Java 7 (de habrá en Java 8)

+0

Por supuesto, esto también coincidirá con los subrayados y otros signos de puntuación de conexión. –

+0

@TimPietzcker eso es cierto, si eso importa, entonces su respuesta sería la mejor opción para el OP (+1 para usted) – stema

+0

@TimPietzcker Bajo 'UNICODE_CHARACTER_CLASS', las llamadas clases POSIX también coinciden por [UTS # 18 Anexo C ] (http://unicode.org/reports/tr18/#Compatibility_Properties); es decir, '\ p {alpha}' se convierte en - si y solo si, cuando se compila bajo el indicador de compilación 'Patrón', es exactamente igual a la propiedad Unicode' Alphabetic = True', que a su vez es algo complicado pero bastante útil, y que sí no incluir la puntuación del conector. Perdón por la frase continua. :) – tchrist

8
boolean foundMatch = name.matches("[\\p{L}\\p{Nd}]*"); 

debería funcionar.

[\p{L}\p{Nd}] coincide con un carácter que sea una letra o un dígito Unicode. El método regex .matches() garantiza que toda la cadena coincida con el patrón.

+1

Se pueden encontrar otras posibles categorías Unicode (por ejemplo, 'L' o' N') [aquí] (http://www.fileformat.info/info/unicode/category/index.htm). – beerbajay

+0

No necesita los refuerzos para las 7 categorías principales. Es posible que también te guste '\ pM', entonces' [\ pL \ pM \ pN] '. Tenga en cuenta que eso ya es una definición más amplia que '\ p {Alphabetic}', porque incluye todas las marcas, no solo algunas de ellas. Eso lo acerca más a la propiedad '\ p {word}' usada para identificadores de programa, que según [UTS # 18 Annec C] (http://unicode.org/reports/tr18/#Compatibility_Properties) es '[\ p { alpha} \ p {gc = Mark} \ p {gc = Digit} \ p {gc = Pc}] ', donde' \ p {alpha} 'es complicado, pero básicamente selecciona solo algunas de las marcas. – tchrist

+0

@TimPietzcker Espera: tu prueba booleana es incorrecta. Todas las cadenas posibles coinciden con cero o más repeticiones de cualquier cosa. No creo que quieras esa estrella. Además, como se comentó en otra parte, aunque es probable que quieras querer, '\ pN' es más que solo dígitos; '\ p {Nd}' son solo dígitos decimales sin números romanos, fracciones vulgares o subíndices y superíndices, etc. Simplemente llama a '\ pN' cualquier número, no cualquier dígito, y estarás en lo cierto. – tchrist

1

Algunas personas, cuando se enfrenta a un problema, pensar "Yo sé, Usaré las expresiones regulares ". Ahora ellos tienen dos problemas.

- Jamie Zawinksi

lo digo en broma, pero iteración a través de la cadena como que está haciendo tendrá un rendimiento en tiempo de ejecución al menos tan bueno como cualquier expresión regular - no hay forma de una expresión regular puede hacer lo quieres más rápido; y no tiene la sobrecarga de compilar un patrón en primer lugar.

Por lo tanto, siempre y cuando:

  • la validación no necesita hacer nada más expresiones regulares similares (no se menciona en la pregunta)
  • la intención del código de bucle a través de la cadena es clara (y si no, refactorice hasta que lo sea)

entonces, ¿por qué reemplazarlo con una expresión regular simplemente porque puede?

+2

Sería interesante hacer una copia de seguridad de este reclamo por medidas. –

+0

+1, puede estar de acuerdo o en desacuerdo, ¡realmente es un enlace interesante! – ManuPK

+0

@Tim: ni siquiera necesitas mediciones. A menos que esté utilizando la computación cuántica, no puede verificar que todos los caracteres en una lista de caracteres (también conocido como una Cadena) sean letras o dígitos sin visitar cada carácter, y detenerse tan pronto como encuentre uno que no lo sea. Como esto es lo que hace el código personalizado, es la cantidad de trabajo mínima posible. Regexes no son mágicos. –

Cuestiones relacionadas