Expressions Regulars en Java
Les expressions regulars (regex) són seqüències de caràcters que defineixen patrons per a cercar, validar i manipular cadenes de text. A Java, són molt útils per a identificar patrons complexos en les cadenes, com ara números de telèfon, adreces de correu electrònic o valors específics.
Usos Comuns de les Expressions Regulars
Alguns exemples d’ús de les expressions regulars són:
- Validació de formats: Comprovar que una data siga en format
dd/mm/yyyy
o que un NIF (Número d’Identificació Fiscal) seguisca el format correcte. - Validació de correu electrònic: Verificar que una adreça de correu complisca amb un format estàndard.
- Validació de contrasenyes: Assegurar-se que una contrasenya continga majúscules, minúscules, números i símbols.
- Extracció de dades: Buscar i extraure números de telèfon, codis postals o qualsevol altra informació que complisca un patró determinat.
- Cerca de patrons: Trobar i comptar quantes vegades es repeteix un fragment dins d’una cadena.
Funcionament Bàsic de les Expressions Regulars
Les expressions regulars recorren una cadena d’esquerra a dreta, buscant coincidències amb el patró definit. Quan un caràcter de la cadena compleix amb el patró, aquest caràcter ja no torna a considerar-se per a futures comprovacions en la mateixa cerca.
Hi ha dos enfocaments principals en la comparació de patrons amb cadenes:
- Trobar coincidències parcials: Determinar si una part de la cadena compleix amb el patró. Per exemple, trobar una data en format
dd/mm/yyyy
dins d’una cadena com “Hui és 12/02/2017”. - Coincidència exacta: Verificar que tota la cadena complisca exactament amb el patró donat. Per exemple, comprovar si “12/02/2017” és exactament una data sense text addicional.
Símbols i Metacaràcters en Expressions Regulars
Els metacaràcters són símbols especials que defineixen el comportament de les expressions regulars. A continuació, es descriuen alguns dels més comuns:
- . : Qualsevol caràcter (excepte salts de línia).
- ^ : Indica que el patró ha de començar al principi de la cadena.
- $ : Indica que el patró ha de finalitzar al final de la cadena.
- [abc] : Coincideix amb qualsevol dels caràcters
a
,b
oc
. - [^abc] : Coincideix amb qualsevol caràcter excepte
a
,b
oc
. - [a-z] : Coincideix amb qualsevol lletra minúscula de la
a
a laz
. A|B
: Coincideix ambA
oB
(operador OR).- \d : Coincideix amb qualsevol dígit (equivalent a
[0-9]
). - \D : Coincideix amb qualsevol caràcter que no siga un dígit (equivalent a
[^0-9]
). - \s : Coincideix amb qualsevol espai en blanc (inclou espais, tabuladors i salts de línia).
- \S : Coincideix amb qualsevol caràcter que no siga un espai en blanc.
- \w : Coincideix amb qualsevol lletra, dígit o subratllat (equivalent a
[A-Za-z0-9_]
). - \W : Coincideix amb qualsevol caràcter que no siga una lletra, dígit o subratllat.
Quantificadors
Els quantificadors determinen quantes vegades un element de l’expressió regular pot aparèixer en una coincidència:
{X}
: Exactament X repeticions.{X,Y}
: Entre X i Y repeticions.{X,}
: Almenys X repeticions.*
: Zero o més repeticions (equivalent a{0,}
).+
: Una o més repeticions (equivalent a{1,}
).?
: Zero o una repetició (equivalent a{0,1}
).
Exemples d’Expressions Regulars
1. Validar un dígit
String regex = "^\\d$";
^
: Indica l’inici de la cadena.\\d
: Representa qualsevol dígit del 0 al 9.$
: Indica el final de la cadena.
Exemple:
"5"
: Vàlid, ja que és un únic dígit."a"
: No vàlid, ja que no és un dígit."12"
: No vàlid, ja que conté més d’un dígit.
2. Validar una paraula de lletres majúscules
String regex = "^[A-Z]+$";
^
: Inici de la cadena.[A-Z]
: Qualsevol lletra majúscula de laA
a laZ
.+
: Almenys una o més repeticions de lletres majúscules.$
: Final de la cadena.
Exemple:
"HELLO"
: Vàlid, només conté lletres majúscules."Hello"
: No vàlid, conté lletres minúscules."123"
: No vàlid, no conté cap lletra.
3. Validar un número enter positiu de fins a 3 dígits
String regex = "^[1-9]\\d{0,2}$";
^
: Inici de la cadena.[1-9]
: El primer dígit ha de ser entre 1 i 9 (per evitar zeros al davant).\\d{0,2}
: Pot tenir de 0 a 2 dígits addicionals.$
: Final de la cadena.
Exemple:
"5"
: Vàlid, ja que és un número de 1 dígit."123"
: Vàlid, ja que és un número de 3 dígits."012"
: No vàlid, comença amb un zero."1000"
: No vàlid, ja que conté més de 3 dígits.
4. Validar una adreça de correu electrònic senzilla
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
^
: Inici de la cadena.[A-Za-z0-9+_.-]+
: Permet lletres, dígits i alguns caràcters especials abans de l’@
.@
: Simbolitza la separació entre el nom d’usuari i el domini.[A-Za-z0-9.-]+
: Permet caràcters alfanumèrics i alguns símbols en el domini.$
: Final de la cadena.
Exemple:
"joan123@gmail.com"
: Vàlid."maria@universitat"
: No vàlid, falta el domini després del punt."pere@empresa.net"
: Vàlid."@gmail.com"
: No vàlid, falta la part de l’usuari.
5. Validar una data en format dd/mm/yyyy
String regex = "^(0[1-9]|[12]\\d|3[01])/(0[1-9]|1[0-2])/\\d{4}$";
^
: Inici de la cadena.(0[1-9]|[12]\\d|3[01])
: Dies de l’1 al 31./
: Separador de la data.(0[1-9]|1[0-2])
: Mesos de l’1 al 12./
: Separador de la data.\\d{4}
: Any de quatre dígits.$
: Final de la cadena.
Exemple:
"12/02/2024"
: Vàlid."31/04/2024"
: Vàlid, tot i que no és una data real (no comprova els dies del mes)."01/13/2024"
: No vàlid, no existeix el mes 13."1/2/2024"
: No vàlid, falta un zero per mantenir el formatdd/mm/yyyy
.
6. Validar un número de telèfon en format internacional
String regex = "^\\+[0-9]{1,3} ?[0-9]{6,14}$";
^\\+
: Comença amb el símbol+
.[0-9]{1,3}
: Codi de país, d’1 a 3 dígits.?
: Espai opcional.[0-9]{6,14}
: De 6 a 14 dígits per al número de telèfon.$
: Final de la cadena.
Exemple:
"+34 123456789"
: Vàlid."+123456789"
: Vàlid."123456789"
: No vàlid, falta el+
del codi de país."+1 12345"
: No vàlid, massa pocs dígits.
7. Validar una contrasenya amb requisits de seguretat
String regex = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@#$%!]).{8,}$";
^
: Inici de la cadena.(?=.*[A-Z])
: Almenys una lletra majúscula.(?=.*[a-z])
: Almenys una lletra minúscula.(?=.*\\d)
: Almenys un dígit.(?=.*[@#$%!])
: Almenys un dels caràcters especials:@
,#
,$
,%
,!
..{8,}
: La contrasenya ha de tenir almenys 8 caràcters.$
: Final de la cadena.
Exemple:
"Password123!"
: Vàlid."password"
: No vàlid, falta una majúscula, un dígit i un caràcter especial."PASSWORD123"
: No vàlid, falta un caràcter especial i una minúscula."Pass1!"
: No vàlid, massa curta.
Pattern i Matcher
Les classes Pattern
i Matcher
en Java ens permeten treballar amb expressions regulars, que són seqüències de caràcters que defineixen patrons per a cercar, validar o manipular textos.
Classe Pattern
La classe Pattern
representa una expressió regular compilada i es pot utilitzar per a crear objectes Matcher
que cerquen coincidències en seqüències de caràcters.
Mètodes principals de Pattern:
-
Pattern.compile(String regex)
: Aquest mètode compila una expressió regular en un objectePattern
. Això és necessari abans de poder buscar coincidències ambMatcher
. -
matcher(CharSequence input)
: Crea un objecteMatcher
per buscar coincidències en una seqüència de caràcters específica, com ara unaString
. -
Pattern.matches(String regex, CharSequence input)
: Un mètode estàtic que comprova si la seqüència de caràcters coincideix completament amb el patró donat. -
split(CharSequence input)
: Divideix la seqüència de caràcters en funció del patró i retorna un array deString
amb les parts resultants.
Classe Matcher
La classe Matcher
es crea a partir d’un objecte Pattern
i permet cercar coincidències d’una expressió regular en una seqüència de caràcters. També proporciona mètodes per a analitzar i manipular aquestes coincidències.
Mètodes principals de Matcher:
-
matches()
: Comprova si tota la seqüència de caràcters coincideix amb l’expressió regular. -
find()
: Cerca la següent coincidència de l’expressió regular en la seqüència de caràcters. Retornatrue
si es troba una coincidència ifalse
en cas contrari. -
group()
: Retorna la subcadena que ha coincidit amb l’expressió regular en la cerca actual. -
start()
: Retorna la posició inicial de la coincidència actual. -
end()
: Retorna la posició final de la coincidència actual. -
replaceAll(String replacement)
: Reemplaça totes les coincidències de l’expressió regular amb la cadena proporcionada.
Exemples pràctics
Exemple 1: Extracció de números de telèfon
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ExtractorDeTelefons {
public static void main(String[] args) {
String text = "El meu número de telèfon és 123-456-789. El de casa és 964-123-456";
String regex = "\\d{3}-\\d{3}-\\d{3}";
Pattern objectePattern = Pattern.compile(regex);
Matcher objecteMatcher = objectePattern.matcher(text);
while (objecteMatcher.find()) {
String phoneNumber = objecteMatcher.group();
System.out.println("El número de telèfon trobat és: " + phoneNumber);
System.out.println("Inici: " + objecteMatcher.start() + ", Fi: " + objecteMatcher.end());
}
}
}
A l’exemple, l’expressió regular \\d{3}-\\d{3}-\\d{3}
busca números de telèfon amb el format 123-456-789
. find()
es fa servir per cercar totes les coincidències, i group()
retorna la subcadena trobada.
Exemple 2: Validació de correu electrònic
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ValidarCorreu {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Introdueix un correu electrònic:");
String email = sc.nextLine();
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,3}$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
if (matcher.matches()) {
System.out.println("L'adreça de correu és vàlida.");
} else {
System.out.println("L'adreça de correu NO és vàlida.");
}
sc.close();
}
}
matches()
comprova si la cadena email
coincideix completament amb el patró d’un correu electrònic vàlid.
Exemple 3: Reemplaçament de paraules ofensives
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Censura {
public static void main(String[] args) {
String frase = "Eres un datil i un abobat.";
String regex = "(datil|abobat)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(frase);
String fraseCensurada = matcher.replaceAll("****");
System.out.println("CENSURAT!!!!: " + fraseCensurada);
}
}
L’exemple anterior utilitza replaceAll()
per substituir totes les coincidències de les paraules “datil” i “abobat” per “**”.
Altres Mètodes
-
lookingAt()
: Verifica si la seqüència de caràcters coincideix amb el patró des del començament, però no necessita que tota la cadena coincideixi. -
quote()
(dePattern
): Permet tractar un text literal com una expressió regular. Això és útil quan es vol buscar una cadena específica sense que els seus caràcters especials s’interpreten com a part d’un patró. -
pattern()
(deMatcher
): Retorna l’objectePattern
associat a unMatcher
.
Les anteriors classes, combinades amb els mètodes que proporcionen, fan que el treball amb expressions regulars a Java siga flexible i potent, permetent des de validacions bàsiques fins a manipulacions avançades de text.