Regex no funciona en String.matches ()

147

Tengo este pequeño código

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("[a-z]"))
    {
        System.out.println(s);
    }
}

Se supone que imprime

dkoe

pero no imprime nada !!

Juan
fuente
41
Java matchespone un ^ al comienzo y un $ al final de las expresiones regulares para usted. Por matches("[a-z]")lo tanto , en realidad buscará / ^ [az] $ / en su lugar.
Robino
Sí @Robino, tienes toda la razón.
Mihir
1
Seguramente, si espera matchesbuscar alguna ocurrencia [a-z], ¿debería coincidir con todas? No esperaría matchesverificar cada uno de los caracteres individualmente contra la expresión regular.
PhilHibbs
@Robino: ¿Dónde se describe / documenta esa funcionalidad?
Toru
@Toru En la página de documentación de Java para String.Matches, ¿dónde más? Un Google informal de "documentación de coincidencias de cadenas de Java" revela, en el resultado superior, la frase "str.matches (regex) produce exactamente el mismo resultado que la expresión". La palabra importante es "exactamente".
Robino

Respuestas:

323

Bienvenido al .matches()método mal nombrado de Java ... Intenta y coincide con TODAS las entradas. Desafortunadamente, otros idiomas han seguido el ejemplo :(

Si desea ver si la expresión regular coincide con un texto de entrada, use a Pattern, a Matchery el .find()método del comparador:

Pattern p = Pattern.compile("[a-z]");
Matcher m = p.matcher(inputstring);
if (m.find())
    // match

Si lo que quiere es ver si una entrada solo tiene letras minúsculas, puede usarla .matches(), pero debe hacer coincidir uno o más caracteres: agregue un +a su clase de caracteres, como en [a-z]+. O use ^[a-z]+$y .find().

fge
fuente
2
Encuentro cientos de tutoriales incompletos en línea. No pude encontrar una buena. ¿Tienes alguna sugerencia?
John
Gracias @fge por explicar .matches(). ¿Puede saber por qué .find()funciona tan lento en este ejemplo ?
Konstantin Konopko
3
¿Qué quieres decir con otros idiomas seguidos ? Por lo que sé, solo C ++ tiene un conjunto equivalente de métodos, regex_searchy regex_match. En Python, re.matchsolo ancla la coincidencia al comienzo de la cadena (como si fuera \Apattern) y Python 3.x tiene un buen .fullmatch()método. En JS, Go, PHP y .NET, no hay métodos regex que anclen implícitamente la coincidencia. ElasticSearch, XML Schema y HTML5 / Validators Los patrones angulares siempre están anclados de forma predeterminada. En Swift / Objective C, hay una manera de anclar el patrón al principio con una opción.
Wiktor Stribiżew
¿Hay alguna forma de hacer esto?
Cardenal - Restablece a Monica el
44

[a-z]coincide con un único carácter entre a y z. Entonces, si su cadena era solo "d", por ejemplo, entonces habría coincidido y se habría impreso.

Debe cambiar su expresión regular para [a-z]+que coincida con uno o más caracteres.

dogbane
fuente
12
Por supuesto, coincide con un solo carácter, ¡eso es lo que hace esa expresión regular! Sin embargo, lo que no está claro (¡y tampoco debería ser el caso!) Es que Java coloca el prefijo ^y el sufijo $alrededor de la expresión regular proporcionada, alterándola de forma no deseada y creando errores extraños. No deberían hacer eso, porque no es así como se quería decir la expresión regular inicial.
klaar
28

String.matchesdevuelve si la cadena completa coincide con la expresión regular, no con cualquier subcadena.

yshavit
fuente
3
Algo que es realmente una triste realidad es que tienes razón. Realmente no sé por qué lo hicieron de esta manera.
Hola Soy Edu Feliz Navidad
16

La implementación de expresiones regulares de Java intenta hacer coincidir la cadena completa

eso es diferente de las expresiones regulares de Perl, que intentan encontrar una parte coincidente

si desea encontrar una cadena con solo caracteres en minúscula, use el patrón [a-z]+

si desea encontrar una cadena que contenga al menos un carácter en minúscula, use el patrón .*[a-z].*

Hachi
fuente
más información aquí
ycomp
3
¿Por qué esto no está documentado ?
Leo Orientis
12

Usado

String[] words = {"{apf","hum_","dkoe","12f"};
    for(String s:words)
    {
        if(s.matches("[a-z]+"))
        {
            System.out.println(s);
        }
    }
Boni
fuente
4

Me he enfrentado al mismo problema una vez:

Pattern ptr = Pattern.compile("^[a-zA-Z][\\']?[a-zA-Z\\s]+$");

¡Lo anterior falló!

Pattern ptr = Pattern.compile("(^[a-zA-Z][\\']?[a-zA-Z\\s]+$)");

Lo anterior funcionó con patrón dentro (y ).

Shanta
fuente
2

Su expresión regular [a-z]no coincide, dkoeya que solo coincide con cadenas de longitud 1. Use algo como [a-z]+.


fuente
-1

debes poner al menos una captura ()en el patrón para que coincida, y corregir un patrón como este:

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("(^[a-z]+$)"))
    {
        System.out.println(s);
    }
}
MohsenB
fuente
Los corchetes no cambiaron nada.
Touniouk
@Touniouk sin corchetes matchesno tiene salida.
MohsenB
-3

Puede hacer que su patrón sea insensible a mayúsculas y minúsculas haciendo:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
Anita Kulkarni
fuente