Cos'è una Regex?
Le espressioni regolari (regex o regexp) sono sequenze di caratteri che definiscono pattern di ricerca. Sono uno degli strumenti più potenti per l'elaborazione di testi, il riconoscimento di pattern e l'estrazione di dati.
Perché Usare le Espressioni Regolari?
Le regex sono essenziali per:
- Validazione di form (email, numeri di telefono, password)
- Estrazione di dati (parsing di log, scraping di pagine web)
- Elaborazione di testi (trova e sostituisci, formattazione)
- Refactoring del codice (rinominare variabili, aggiornare sintassi)
- Sanitizzazione input (sicurezza, prevenzione attacchi injection)
Come Leggere Questa Cheat Sheet
Questa guida è organizzata in sezioni progressive:
- Fondamenti - Sintassi e pattern di base
- Funzionalità Avanzate - Lookaround, gruppi nominati, Unicode
- Specifico per Linguaggio - Esempi in Python, JavaScript, PHP, C#, Java, Go, Ruby
- Regex in VS Code - Trasformazioni trova/sostituisci con oltre 20 esempi
- Pattern Comuni - Pattern copia-incolla per email, URL, date, ecc.
- Casi d'Uso Pratici - Applicazioni del mondo reale
- Risoluzione Problemi - Errori comuni e consigli sulle prestazioni
Ogni sezione include:
- Spiegazioni chiare
- Esempi visivi
- Snippet di codice che puoi copiare
- Suggerimenti professionali e insidie
Caratteri Letterali
La regex più semplice è una sequenza di caratteri letterali:
abc
Corrisponde a: "abc" in "La sequenza abc"
Sensibilità alle Maiuscole
Per impostazione predefinita, le regex sono sensibili alle maiuscole:
Ciaocorrisponde a "Ciao" ma NON a "ciao"- Usa il flag
iper corrispondenza insensibile alle maiuscole:/ciao/i
Caratteri Speciali (Metacaratteri)
Questi 12 caratteri hanno significato speciale nelle regex e devono essere escapati con \ per corrispondere letteralmente:
. ^ $ * + ? { } [ ] \ | ( )
Esempi:
\.corrisponde a un punto letterale\$corrisponde a un segno di euro\(corrisponde a una parentesi letterale
| Carattere | Escape | Esempio | Corrisponde |
|---|---|---|---|
. (punto) |
\. |
3\.14 |
"3.14" |
$ (dollaro) |
\$ |
\$100 |
"$100" |
* (asterisco) |
\* |
a\*b |
"a*b" |
Classi di Caratteri
Classi di Caratteri Predefinite
| Pattern | Descrizione | Equivalente | Esempio | Corrisponde |
|---|---|---|---|---|
\d |
Qualsiasi cifra | [0-9] |
\d\d |
"42" |
\D |
Qualsiasi non-cifra | [^0-9] |
\D+ |
"abc" |
\w |
Carattere word | [a-zA-Z0-9_] |
\w+ |
"ciao_123" |
\W |
Carattere non-word | [^a-zA-Z0-9_] |
\W |
"@", "#" |
\s |
Spazio bianco | [ \t\n\r\f\v] |
\s+ |
" " (spazi) |
\S |
Non-spazio | [^ \t\n\r\f\v] |
\S+ |
"ciao" |
. |
Qualsiasi carattere eccetto newline | - | a.c |
"abc", "a1c" |
Suggerimento Pro: \w NON include lettere Unicode per impostazione predefinita. Usa \p{L} per supporto Unicode (JavaScript/Python).
Classi di Caratteri Personalizzate
| Pattern | Descrizione | Esempio | Corrisponde |
|---|---|---|---|
[abc] |
Corrisponde a qualsiasi di a, b, o c | [aeiou] |
Vocali: "a", "e", "i", "o", "u" |
[^abc] |
Corrisponde a qualsiasi tranne a, b, o c | [^0-9] |
Non-cifre |
[a-z] |
Intervallo: lettere minuscole | [a-z]+ |
"ciao" |
[A-Z] |
Intervallo: lettere maiuscole | [A-Z]+ |
"CIAO" |
[0-9] |
Intervallo: cifre | [0-9]{4} |
"2025" |
[a-zA-Z] |
Combinato: tutte le lettere | [a-zA-Z0-9] |
Alfanumerico |
Esempi:
[aeiou] → Corrisponde a qualsiasi vocale
[^aeiou] → Corrisponde a qualsiasi consonante (non vocale)
[a-z0-9] → Corrisponde a lettere minuscole e cifre
[a-zA-Z0-9_] → Uguale a \w (caratteri word)
Quantificatori
I quantificatori specificano quante volte un pattern deve corrispondere.
Quantificatori Base
| Pattern | Descrizione | Esempio | Corrisponde |
|---|---|---|---|
* |
0 o più | ab*c |
"ac", "abc", "abbc", "abbbc" |
+ |
1 o più | ab+c |
"abc", "abbc" (NON "ac") |
? |
0 o 1 (opzionale) | colou?r |
"color", "colour" |
{n} |
Esattamente n volte | \d{4} |
"2025" (esattamente 4 cifre) |
{n,} |
n o più volte | \d{2,} |
"42", "123", "9999" |
{n,m} |
Tra n e m volte | \d{2,4} |
"42", "123", "2025" |
Quantificatori Greedy vs. Lazy
Greedy (predefinito): Corrisponde al massimo possibile
<.*> → Corrisponde: "<div>Ciao</div>" (intera stringa)
Lazy (non-greedy): Corrisponde al minimo possibile (aggiungi ? dopo il quantificatore)
<.*?> → Corrisponde: "<div>" e "</div>" separatamente
| Greedy | Lazy | Descrizione |
|---|---|---|
* |
*? |
0 o più (lazy) |
+ |
+? |
1 o più (lazy) |
? |
?? |
0 o 1 (lazy) |
{n,m} |
{n,m}? |
Tra n e m (lazy) |
Esempio:
Testo: "Ciao" e "Mondo"
".*"corrisponde:"Ciao" e "Mondo"(greedy)".*?"corrisponde:"Ciao"e"Mondo"separatamente (lazy)
Ancoraggi e Confini
Gli ancoraggi corrispondono a posizioni, non caratteri.
| Pattern | Descrizione | Esempio | Corrisponde |
|---|---|---|---|
^ |
Inizio stringa/riga | ^Ciao |
"Ciao Mondo" (all'inizio) |
$ |
Fine stringa/riga | Mondo$ |
"Ciao Mondo" (alla fine) |
\b |
Confine parola | \bgatto\b |
"gatto" in "Il gatto seduto" (NON "gattone") |
\B |
Non-confine parola | \Bgatt |
"gattone" (gatt NON al confine) |
\A |
Inizio stringa (non riga) | \ACiao |
Corrisponde solo se "Ciao" è proprio all'inizio |
\z |
Fine stringa (non riga) | Mondo\z |
Corrisponde solo se "Mondo" è proprio alla fine |
\Z |
Fine stringa (prima del newline finale) | Mondo\Z |
Corrisponde "Mondo" o "Mondo\n" |
Esempi:
^gatto$ → Corrisponde: "gatto" (l'intera riga è "gatto")
\bgatto\b → Corrisponde: "gatto" in "il gatto seduto" (parola intera)
\Bgatt → Corrisponde: "gatt" in "gattone" (NON al confine)
Modalità Multilinea (flag m):
- Senza
m:^e$corrispondono inizio/fine dell'intera stringa - Con
m:^e$corrispondono inizio/fine di ogni riga
Gruppi e Alternanza
Gruppi di Cattura
I gruppi di cattura (...) ricordano il testo corrispondente:
(\d+)-(\d+) → Corrisponde: "123-456"
Gruppo 1: "123"
Gruppo 2: "456"
Riferimenti all'indietro (riutilizza gruppi catturati):
(\w)\1 → Corrisponde: "aa", "bb", "cc" (carattere ripetuto)
(\w+) \1 → Corrisponde: "ciao ciao" (parola ripetuta)
Gruppi Non-Cattura
Usa (?:...) quando serve raggruppare ma non serve catturare:
(?:https?://) → Raggruppa "http://" o "https://" senza catturare
Perché usare non-cattura?
- Prestazioni migliori (nessun overhead di memoria)
- Riferimenti all'indietro più puliti (i gruppi numerati contano solo i gruppi di cattura)
Alternanza (OR)
Usa | per "corrisponde questo O quello":
gatto|cane → Corrisponde: "gatto" o "cane"
gr(i|a)gio → Corrisponde: "grigio" o "graggio"
Esempi:
(Sig|Sig\.ra|Dott)\.? → Corrisponde: "Sig.", "Sig.ra", "Dott."
https?:// → Corrisponde: "http://" o "https://"
Asserzioni Lookaround
I lookaround sono asserzioni a larghezza zero che corrispondono a una posizione (come gli ancoraggi) ma con condizioni.
Lookahead Positivo (?=...)
Corrisponde se il pattern avanti corrisponde (ma non lo consuma):
\d(?=px) → Corrisponde: "10" in "10px" (NON la parte "px")
Caso d'uso: Validazione password
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$
Scomposizione:
(?=.*[A-Z])- Deve contenere maiuscola(?=.*[a-z])- Deve contenere minuscola(?=.*\d)- Deve contenere cifra(?=.*[@$!%*?&])- Deve contenere carattere speciale.{8,}- Almeno 8 caratteri
Lookahead Negativo (?!...)
Corrisponde se il pattern avanti NON corrisponde:
\d(?!px) → Corrisponde: "10" in "10em" (NON "10px")
Caso d'uso: Escludere certe parole
\b(?!test)\w+ → Corrisponde parole che NON iniziano con "test"
Lookbehind Positivo (?<=...)
Corrisponde se il pattern indietro corrisponde:
(?<=€)\d+ → Corrisponde: "100" in "€100" (NON la parte "€")
Caso d'uso: Estrarre prezzi
(?<=Prezzo: €)\d+,\d{2} → Corrisponde: "29,99" in "Prezzo: €29,99"
Lookbehind Negativo (?<!...)
Corrisponde se il pattern indietro NON corrisponde:
(?<!€)\d+ → Corrisponde: "100" ma NON in "€100"
Tabella Riepilogativa:
| Tipo | Sintassi | Descrizione | Esempio |
|---|---|---|---|
| Lookahead Positivo | (?=...) |
Corrisponde se seguito da... | q(?=u) corrisponde "q" in "queen" |
| Lookahead Negativo | (?!...) |
Corrisponde se NON seguito da... | q(?!u) corrisponde "q" in "iraq" |
| Lookbehind Positivo | (?<=...) |
Corrisponde se preceduto da... | (?<=€)\d+ corrisponde "10" in "€10" |
| Lookbehind Negativo | (?<!...) |
Corrisponde se NON preceduto da... | (?<!€)\d+ corrisponde "10" in "10" |
Gruppi di Cattura Nominati
I gruppi nominati (?<nome>...) rendono le regex più leggibili:
JavaScript:
const dateRegex = /(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})/;
const match = '2025-01-17'.match(dateRegex);
console.log(match.groups.anno); // "2025"
console.log(match.groups.mese); // "01"
console.log(match.groups.giorno); // "17"
Python:
import re
pattern = r'(?P<anno>\d{4})-(?P<mese>\d{2})-(?P<giorno>\d{2})'
match = re.search(pattern, '2025-01-17')
print(match.group('anno')) # "2025"
print(match.group('mese')) # "01"
print(match.group('giorno')) # "17"
C#:
var pattern = @"(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})";
var match = Regex.Match("2025-01-17", pattern);
Console.WriteLine(match.Groups["anno"].Value); // "2025"
Gruppi Atomici e Quantificatori Possessivi
Gruppi Atomici (?>...)
Una volta corrispondente, il gruppo non fa backtrack. Previene backtracking catastrofico:
(?>\d+)bar → Corrisponde: "123bar" (veloce)
Senza gruppo atomico:
\d+bar → Prova: "123bar", "12bar", "1bar" (lento su mancata corrispondenza)
Quantificatori Possessivi
| Greedy | Possessivo | Descrizione |
|---|---|---|
* |
*+ |
0 o più (nessun backtracking) |
+ |
++ |
1 o più (nessun backtracking) |
? |
?+ |
0 o 1 (nessun backtracking) |
Caso d'uso: Previeni backtracking catastrofico su pattern complessi.
Supporto Unicode
I motori regex moderni supportano categorie e script Unicode.
Categorie Unicode \p{...}
JavaScript (ES2018+):
const letters = /\p{L}+/u; // Qualsiasi lettera (qualsiasi lingua)
const numbers = /\p{N}+/u; // Qualsiasi numero
const currency = /\p{Sc}/u; // Simboli di valuta
Python:
import regex # Nota: richiede modulo 'regex', non 're'
letters = regex.compile(r'\p{L}+')
Categorie Unicode Comuni:
| Categoria | Descrizione | Esempio |
|---|---|---|
\p{L} |
Lettera | "a", "字", "א" |
\p{N} |
Numero | "1", "①", "一" |
\p{S} |
Simbolo | "$", "©", "♥" |
\p{Sc} |
Simbolo valuta | "$", "€", "¥" |
\p{P} |
Punteggiatura | ".", "!", "?" |
\p{Z} |
Separatore | Spazio, tab |
Script Unicode:
/\p{Script=Greek}/u → Corrisponde lettere greche: "α", "β", "γ"
/\p{Script=Cyrillic}/u → Corrisponde cirillico: "а", "б", "в"
/\p{Script=Han}/u → Corrisponde caratteri cinesi
Negazione:
/\P{L}+/u → Corrisponde a qualsiasi cosa che NON sia una lettera
Modificatori e Flag
I flag cambiano come i pattern regex vengono interpretati.
| Flag | Nome | Descrizione | Esempio |
|---|---|---|---|
i |
Insensibile maiuscole | Ignora maiuscole | /ciao/i corrisponde "Ciao" |
g |
Globale | Trova tutte le corrispondenze | /gatto/g trova tutti i "gatto" |
m |
Multilinea | ^ e $ corrispondono inizi/fini riga |
/^ciao/m |
s |
Dotall | . corrisponde anche a newline |
/a.b/s corrisponde "a\nb" |
u |
Unicode | Abilita funzionalità Unicode | /\p{L}+/u |
x |
Esteso | Ignora spazi bianchi (free-spacing) | Permette commenti |
y |
Sticky | Corrisponde a posizione esatta | Solo JavaScript |
Esempi:
Insensibile maiuscole (i):
/ciao/i.test('CIAO') // true
Globale (g):
'gatto cane gatto'.match(/gatto/g) // ["gatto", "gatto"]
Multilinea (m):
const text = 'Riga 1\nRiga 2';
/^Riga 2/m.test(text) // true (senza 'm': false)
Dotall (s):
/a.b/s.test('a\nb') // true (senza 's': false)
Modificatori Inline
Applica flag a parte del pattern:
(?i)ciao → "ciao" insensibile maiuscole
(?-i)MONDO → "MONDO" sensibile maiuscole
(?i:ciao) → Solo "ciao" è insensibile maiuscole
Pattern Condizionali
Sintassi: (?(condizione)vero|falso)
Esempio: Corrispondere stringhe quotate o non quotate
("|')?[^"'\r\n]*(?(1)\1)
Scomposizione:
("|')?- Cattura opzionalmente virgoletta di apertura[^"'\r\n]*- Corrisponde contenuto(?(1)\1)- Se gruppo 1 corrispondente (virgoletta apertura), corrisponde stessa virgoletta chiusura
Corrisponde:
"ciao"✅'mondo'✅test✅ (nessuna virgoletta)"misto'❌ (virgolette non corrispondenti)
Commenti nelle Regex
Commenti Inline (?# commento)
\d{3}(?# prefisso)-\d{3}(?# centrale)-\d{4}(?# numero)
Modalità Free-Spacing (flag x)
Ignora spazi bianchi e permette commenti:
(?x)
\d{3} # prefisso
- # separatore
\d{3} # centrale
- # separatore
\d{4} # numero
Molto più leggibile per pattern complessi!
Questa sezione dimostra come usare le regex in 7 linguaggi di programmazione popolari. Ogni linguaggio ha la sua API regex, ma la sintassi dei pattern rimane per lo più consistente.
JavaScript / Node.js
Creare Pattern Regex
// Notazione letterale (più comune)
const pattern1 = /\d{3}-\d{4}/;
// Costruttore (quando il pattern è dinamico)
const pattern2 = new RegExp('\\d{3}-\\d{4}');
// Nota: I backslash devono essere escapati nelle stringhe
// Con flag
const pattern3 = /ciao/gi; // Globale, insensibile maiuscole
Metodi String
// .match() - Trova corrispondenze
const text = 'Contatto: 123-4567 o 987-6543';
const matches = text.match(/\d{3}-\d{4}/g);
console.log(matches); // ["123-4567", "987-6543"]
// .matchAll() - Ottieni tutte le corrispondenze con gruppi (ES2020)
const emailPattern = /([\w.-]+)@([\w.-]+\.[a-z]{2,})/gi;
const emails = 'admin@esempio.it, utente@test.org';
for (const match of emails.matchAll(emailPattern)) {
console.log(`Utente: ${match[1]}, Dominio: ${match[2]}`);
}
// Utente: admin, Dominio: esempio.it
// Utente: utente, Dominio: test.org
// .search() - Trova posizione della prima corrispondenza
const pos = 'Ciao Mondo'.search(/Mondo/);
console.log(pos); // 5
// .replace() - Sostituisci corrispondenze
const phone = '(+39) 333 123 4567';
const cleaned = phone.replace(/[^\d]/g, '');
console.log(cleaned); // "393331234567"
// .replaceAll() - Sostituisci tutte le corrispondenze (ES2021)
const text2 = 'gatto cane gatto';
const result = text2.replaceAll(/gatto/g, 'uccello');
console.log(result); // "uccello cane uccello"
// .split() - Dividi per pattern
const csv = 'mela,banana, arancia , uva';
const fruits = csv.split(/\s*,\s*/);
console.log(fruits); // ["mela", "banana", "arancia", "uva"]
Metodi RegExp
// .test() - Restituisce booleano
const isEmail = /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i;
console.log(isEmail.test('utente@esempio.it')); // true
// .exec() - Restituisce dettagli corrispondenza (o null)
const pattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = pattern.exec('Data: 2025-01-17');
if (match) {
console.log(match[0]); // "2025-01-17" (corrispondenza completa)
console.log(match[1]); // "2025" (gruppo 1)
console.log(match[2]); // "01" (gruppo 2)
console.log(match[3]); // "17" (gruppo 3)
}
Gruppi Nominati (ES2018+)
const pattern = /(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})/;
const match = '2025-01-17'.match(pattern);
console.log(match.groups.anno); // "2025"
console.log(match.groups.mese); // "01"
console.log(match.groups.giorno); // "17"
// Riferimenti nominati all'indietro
const dupeWord = /\b(?<parola>\w+)\s+\k<parola>\b/i;
console.log(dupeWord.test('ciao ciao')); // true
Supporto Unicode (ES2018+)
// Corrisponde qualsiasi lettera (incluse accentate, cinesi, arabe, ecc.)
const letters = /\p{L}+/u;
console.log(letters.test('caffè')); // true
console.log(letters.test('你好')); // true
// Corrisponde emoji
const emoji = /\p{Emoji}/u;
console.log(emoji.test('Ciao 👋')); // true
Python
Il Modulo re
import re
# Compila pattern (raccomandato per riutilizzo)
pattern = re.compile(r'\d{3}-\d{4}')
# Oppure usa direttamente
re.search(r'\d{3}-\d{4}', 'Chiama 123-4567')
Funzioni Core
import re
# re.search() - Trova prima corrispondenza
match = re.search(r'\d{3}-\d{4}', 'Contatto: 123-4567 o 987-6543')
if match:
print(match.group()) # "123-4567"
print(match.start()) # 10 (posizione)
print(match.end()) # 18
# re.match() - Corrisponde all'INIZIO della stringa
match = re.match(r'\d+', '123 Via Roma')
print(match.group() if match else None) # "123"
match = re.match(r'\d+', 'Via Roma 123')
print(match) # None (non inizia con cifra)
# re.fullmatch() - Corrisponde INTERA stringa
result = re.fullmatch(r'\d{3}-\d{4}', '123-4567')
print(bool(result)) # True
result = re.fullmatch(r'\d{3}-\d{4}', 'Chiama 123-4567')
print(bool(result)) # False (testo extra)
# re.findall() - Trova tutte le corrispondenze (restituisce lista)
text = 'Prezzi: €10, €25, €100'
prices = re.findall(r'€(\d+)', text)
print(prices) # ['10', '25', '100']
# re.finditer() - Trova tutte le corrispondenze (restituisce iteratore)
for match in re.finditer(r'€(\d+)', text):
print(f'Trovato €{match.group(1)} alla posizione {match.start()}')
# Trovato €10 alla posizione 8
# Trovato €25 alla posizione 13
# Trovato €100 alla posizione 18
# re.sub() - Sostituisci corrispondenze
phone = '(+39) 333 123 4567'
cleaned = re.sub(r'[^\d]', '', phone)
print(cleaned) # "393331234567"
# re.split() - Dividi per pattern
csv = 'mela,banana, arancia , uva'
fruits = re.split(r'\s*,\s*', csv)
print(fruits) # ['mela', 'banana', 'arancia', 'uva']
Gruppi e Gruppi Nominati
import re
# Gruppi numerati
pattern = r'(\d{4})-(\d{2})-(\d{2})'
match = re.search(pattern, 'Data: 2025-01-17')
if match:
print(match.group(0)) # "2025-01-17" (corrispondenza completa)
print(match.group(1)) # "2025"
print(match.group(2)) # "01"
print(match.group(3)) # "17"
print(match.groups()) # ('2025', '01', '17')
# Gruppi nominati (?P<nome>...)
pattern = r'(?P<anno>\d{4})-(?P<mese>\d{2})-(?P<giorno>\d{2})'
match = re.search(pattern, '2025-01-17')
if match:
print(match.group('anno')) # "2025"
print(match.group('mese')) # "01"
print(match.group('giorno')) # "17"
print(match.groupdict()) # {'anno': '2025', 'mese': '01', 'giorno': '17'}
Flag
import re
# Insensibile maiuscole
re.search(r'ciao', 'CIAO', re.IGNORECASE) # o re.I
# Multilinea (^ e $ corrispondono inizi/fini riga)
re.search(r'^Riga 2', 'Riga 1\nRiga 2', re.MULTILINE) # o re.M
# Dotall (. corrisponde newline)
re.search(r'a.b', 'a\nb', re.DOTALL) # o re.S
# Verbose (modalità free-spacing con commenti)
pattern = re.compile(r'''
\d{3} # prefisso
- # separatore
\d{3} # centrale
- # separatore
\d{4} # numero
''', re.VERBOSE) # o re.X
# Combina flag con |
pattern = re.compile(r'ciao', re.IGNORECASE | re.MULTILINE)
Sostituzione con Funzioni
import re
# Usa funzione per sostituzioni dinamiche
def double_number(match):
num = int(match.group())
return str(num * 2)
text = 'Ho 5 mele e 10 arance'
result = re.sub(r'\d+', double_number, text)
print(result) # "Ho 10 mele e 20 arance"
# Con gruppi nominati
def format_name(match):
return f"{match.group('cognome').upper()}, {match.group('nome')}"
pattern = r'(?P<nome>\w+)\s+(?P<cognome>\w+)'
text = 'Mario Rossi'
result = re.sub(pattern, format_name, text)
print(result) # "ROSSI, Mario"
PHP
Funzioni PCRE
<?php
// preg_match() - Trova prima corrispondenza
$pattern = '/\d{3}-\d{4}/';
$text = 'Contatto: 123-4567 o 987-6543';
if (preg_match($pattern, $text, $matches)) {
echo $matches[0]; // "123-4567"
}
// preg_match_all() - Trova tutte le corrispondenze
preg_match_all('/\d{3}-\d{4}/', $text, $matches);
print_r($matches[0]); // ["123-4567", "987-6543"]
// preg_replace() - Sostituisci corrispondenze
$phone = '(+39) 333 123 4567';
$cleaned = preg_replace('/[^\d]/', '', $phone);
echo $cleaned; // "393331234567"
// preg_split() - Dividi per pattern
$csv = 'mela,banana, arancia , uva';
$fruits = preg_split('/\s*,\s*/', $csv);
print_r($fruits); // ["mela", "banana", "arancia", "uva"]
// preg_grep() - Filtra array per pattern
$words = ['mela', 'banana', 'albicocca', 'arancia'];
$aWords = preg_grep('/^a/', $words);
print_r($aWords); // ["albicocca", "arancia"]
?>
Gruppi Nominati
<?php
$pattern = '/(?P<anno>\d{4})-(?P<mese>\d{2})-(?P<giorno>\d{2})/';
$text = '2025-01-17';
if (preg_match($pattern, $text, $matches)) {
echo $matches['anno']; // "2025"
echo $matches['mese']; // "01"
echo $matches['giorno']; // "17"
}
?>
Modificatori (Flag)
<?php
// i - Insensibile maiuscole
preg_match('/ciao/i', 'CIAO'); // Corrisponde
// m - Multilinea
preg_match('/^Riga 2/m', "Riga 1\nRiga 2"); // Corrisponde
// s - Dotall (. corrisponde newline)
preg_match('/a.b/s', "a\nb"); // Corrisponde
// x - Free-spacing (ignora spazi bianchi)
$pattern = '/
\d{3} # prefisso
- # separatore
\d{3} # centrale
- # separatore
\d{4} # numero
/x';
// u - Supporto UTF-8
preg_match('/\w+/u', 'caffè'); // Corrisponde (include è)
// Combina modificatori
preg_match('/ciao/imu', $text);
?>
Sostituzione con Callback
<?php
$text = 'Ho 5 mele e 10 arance';
$result = preg_replace_callback('/\d+/', function($matches) {
return (int)$matches[0] * 2;
}, $text);
echo $result; // "Ho 10 mele e 20 arance"
?>
C# (.NET)
Classe Regex
using System;
using System.Text.RegularExpressions;
// Metodi statici (uso semplice)
string text = "Contatto: 123-4567 o 987-6543";
Match match = Regex.Match(text, @"\d{3}-\d{4}");
if (match.Success)
{
Console.WriteLine(match.Value); // "123-4567"
}
// Trova tutte le corrispondenze
MatchCollection matches = Regex.Matches(text, @"\d{3}-\d{4}");
foreach (Match m in matches)
{
Console.WriteLine(m.Value);
}
// Output:
// 123-4567
// 987-6543
// Sostituisci
string phone = "(+39) 333 123 4567";
string cleaned = Regex.Replace(phone, @"[^\d]", "");
Console.WriteLine(cleaned); // "393331234567"
// Dividi
string csv = "mela,banana, arancia , uva";
string[] fruits = Regex.Split(csv, @"\s*,\s*");
// ["mela", "banana", "arancia", "uva"]
Regex Compilata (Prestazioni Migliori)
using System.Text.RegularExpressions;
// Compila per riutilizzo (molto più veloce per uso ripetuto)
Regex pattern = new Regex(@"\d{3}-\d{4}", RegexOptions.Compiled);
string text = "Contatto: 123-4567";
Match match = pattern.Match(text);
if (match.Success)
{
Console.WriteLine(match.Value);
}
RegexOptions (Flag)
using System.Text.RegularExpressions;
// Insensibile maiuscole
Regex.IsMatch("CIAO", "ciao", RegexOptions.IgnoreCase);
// Multilinea
Regex.Match("Riga 1\nRiga 2", "^Riga 2", RegexOptions.Multiline);
// Singleline (. corrisponde newline)
Regex.Match("a\nb", "a.b", RegexOptions.Singleline);
// Compilata (prestazioni migliori)
var pattern = new Regex(@"\d+", RegexOptions.Compiled);
// Combina opzioni
var opts = RegexOptions.IgnoreCase | RegexOptions.Multiline;
Regex.Match(text, pattern, opts);
Gruppi Nominati
using System;
using System.Text.RegularExpressions;
string pattern = @"(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})";
Match match = Regex.Match("2025-01-17", pattern);
if (match.Success)
{
Console.WriteLine(match.Groups["anno"].Value); // "2025"
Console.WriteLine(match.Groups["mese"].Value); // "01"
Console.WriteLine(match.Groups["giorno"].Value); // "17"
}
Sostituzione con MatchEvaluator
using System;
using System.Text.RegularExpressions;
string text = "Ho 5 mele e 10 arance";
string result = Regex.Replace(text, @"\d+", match =>
{
int num = int.Parse(match.Value);
return (num * 2).ToString();
});
Console.WriteLine(result); // "Ho 10 mele e 20 arance"
Java
Classi Pattern e Matcher
import java.util.regex.Pattern;
import java.util.regex.Matcher;
// Compila pattern
Pattern pattern = Pattern.compile("\\d{3}-\\d{4}");
String text = "Contatto: 123-4567 o 987-6543";
// Crea matcher
Matcher matcher = pattern.matcher(text);
// Trova prima corrispondenza
if (matcher.find()) {
System.out.println(matcher.group()); // "123-4567"
}
// Trova tutte le corrispondenze
matcher.reset(); // Resetta all'inizio
while (matcher.find()) {
System.out.println(matcher.group());
}
// Output:
// 123-4567
// 987-6543
Metodi String
// matches() - Verifica se INTERA stringa corrisponde
boolean isPhone = "123-4567".matches("\\d{3}-\\d{4}");
System.out.println(isPhone); // true
// replaceAll() - Sostituisci tutte le corrispondenze
String phone = "(+39) 333 123 4567";
String cleaned = phone.replaceAll("[^\\d]", "");
System.out.println(cleaned); // "393331234567"
// replaceFirst() - Sostituisci prima corrispondenza
String text = "gatto cane gatto";
String result = text.replaceFirst("gatto", "uccello");
System.out.println(result); // "uccello cane gatto"
// split() - Dividi per pattern
String csv = "mela,banana, arancia , uva";
String[] fruits = csv.split("\\s*,\\s*");
// ["mela", "banana", "arancia", "uva"]
Flag Pattern
import java.util.regex.Pattern;
// Insensibile maiuscole
Pattern pattern = Pattern.compile("ciao", Pattern.CASE_INSENSITIVE);
// Multilinea
Pattern.compile("^Riga 2", Pattern.MULTILINE);
// Dotall (. corrisponde newline)
Pattern.compile("a.b", Pattern.DOTALL);
// Commenti (free-spacing)
Pattern.compile("""
\\d{3} # prefisso
- # separatore
\\d{3} # centrale
- # separatore
\\d{4} # numero
""", Pattern.COMMENTS);
// Combina flag
int flags = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE;
Pattern.compile("pattern", flags);
Gruppi Nominati
import java.util.regex.Pattern;
import java.util.regex.Matcher;
Pattern pattern = Pattern.compile("(?<anno>\\d{4})-(?<mese>\\d{2})-(?<giorno>\\d{2})");
Matcher matcher = pattern.matcher("2025-01-17");
if (matcher.find()) {
System.out.println(matcher.group("anno")); // "2025"
System.out.println(matcher.group("mese")); // "01"
System.out.println(matcher.group("giorno")); // "17"
}
Sostituzione Avanzata
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "Ho 5 mele e 10 arance";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
int num = Integer.parseInt(matcher.group());
matcher.appendReplacement(result, String.valueOf(num * 2));
}
matcher.appendTail(result);
System.out.println(result); // "Ho 10 mele e 20 arance"
Go (Golang)
Il Package regexp
package main
import (
"fmt"
"regexp"
)
func main() {
// Compila pattern
pattern := regexp.MustCompile(`\d{3}-\d{4}`)
text := "Contatto: 123-4567 o 987-6543"
// Trova prima corrispondenza
match := pattern.FindString(text)
fmt.Println(match) // "123-4567"
// Trova tutte le corrispondenze
matches := pattern.FindAllString(text, -1)
fmt.Println(matches) // [123-4567 987-6543]
// Verifica se corrisponde
isMatch := pattern.MatchString("123-4567")
fmt.Println(isMatch) // true
// Sostituisci tutto
phone := "(+39) 333 123 4567"
cleaned := regexp.MustCompile(`[^\d]`).ReplaceAllString(phone, "")
fmt.Println(cleaned) // "393331234567"
// Dividi
csv := "mela,banana, arancia , uva"
fruits := regexp.MustCompile(`\s*,\s*`).Split(csv, -1)
fmt.Println(fruits) // [mela banana arancia uva]
}
Submatch (Gruppi)
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
text := "Data: 2025-01-17"
// FindStringSubmatch restituisce [completo, gruppo1, gruppo2, ...]
matches := pattern.FindStringSubmatch(text)
if matches != nil {
fmt.Println(matches[0]) // "2025-01-17" (corrispondenza completa)
fmt.Println(matches[1]) // "2025" (gruppo 1)
fmt.Println(matches[2]) // "01" (gruppo 2)
fmt.Println(matches[3]) // "17" (gruppo 3)
}
// FindAllStringSubmatch per tutte le corrispondenze
text2 := "Date: 2025-01-17 e 2024-12-31"
allMatches := pattern.FindAllStringSubmatch(text2, -1)
for _, match := range allMatches {
fmt.Printf("Anno: %s, Mese: %s, Giorno: %s\n", match[1], match[2], match[3])
}
// Anno: 2025, Mese: 01, Giorno: 17
// Anno: 2024, Mese: 12, Giorno: 31
}
Gruppi Nominati
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(?P<anno>\d{4})-(?P<mese>\d{2})-(?P<giorno>\d{2})`)
text := "2025-01-17"
match := pattern.FindStringSubmatch(text)
if match != nil {
// Ottieni indici gruppi nominati
names := pattern.SubexpNames()
result := make(map[string]string)
for i, name := range names {
if i != 0 && name != "" {
result[name] = match[i]
}
}
fmt.Println(result["anno"]) // "2025"
fmt.Println(result["mese"]) // "01"
fmt.Println(result["giorno"]) // "17"
}
}
Sostituzione con Funzioni
package main
import (
"fmt"
"regexp"
"strconv"
)
func main() {
text := "Ho 5 mele e 10 arance"
pattern := regexp.MustCompile(`\d+`)
result := pattern.ReplaceAllStringFunc(text, func(s string) string {
num, _ := strconv.Atoi(s)
return strconv.Itoa(num * 2)
})
fmt.Println(result) // "Ho 10 mele e 20 arance"
}
Ruby
Letterali Regex
# Notazione letterale
pattern = /\d{3}-\d{4}/
# Con flag
pattern_ci = /ciao/i # Insensibile maiuscole
pattern_multi = /^riga/m # Multilinea
# Costruttore (per pattern dinamici)
pattern = Regex.new('\d{3}-\d{4}')
Metodi String
text = 'Contatto: 123-4567 o 987-6543'
# match() - Restituisce MatchData o nil
match = text.match(/\d{3}-\d{4}/)
if match
puts match[0] # "123-4567"
end
# scan() - Trova tutte le corrispondenze
matches = text.scan(/\d{3}-\d{4}/)
puts matches # ["123-4567", "987-6543"]
# =~ operatore - Restituisce indice della prima corrispondenza
index = text =~ /\d{3}-\d{4}/
puts index # 10
# sub() - Sostituisci prima corrispondenza
result = 'gatto cane gatto'.sub(/gatto/, 'uccello')
puts result # "uccello cane gatto"
# gsub() - Sostituisci tutte le corrispondenze
phone = '(+39) 333 123 4567'
cleaned = phone.gsub(/[^\d]/, '')
puts cleaned # "393331234567"
# split() - Dividi per pattern
csv = 'mela,banana, arancia , uva'
fruits = csv.split(/\s*,\s*/)
puts fruits # ["mela", "banana", "arancia", "uva"]
Gruppi di Cattura
pattern = /(\d{4})-(\d{2})-(\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[0] # "2025-01-17" (corrispondenza completa)
puts match[1] # "2025" (gruppo 1)
puts match[2] # "01" (gruppo 2)
puts match[3] # "17" (gruppo 3)
end
Gruppi Nominati
pattern = /(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[:anno] # "2025"
puts match[:mese] # "01"
puts match[:giorno] # "17"
end
Sostituzione con Blocchi
text = 'Ho 5 mele e 10 arance'
result = text.gsub(/\d+/) { |num| (num.to_i * 2).to_s }
puts result # "Ho 10 mele e 20 arance"
# Con gruppi nominati
pattern = /(?<nome>\w+)\s+(?<cognome>\w+)/
text = 'Mario Rossi'
result = text.gsub(pattern) do |match|
m = Regexp.last_match
"#{m[:cognome].upcase}, #{m[:nome]}"
end
puts result # "ROSSI, Mario"
Flag
# i - Insensibile maiuscole
/ciao/i.match('CIAO') # Corrisponde
# m - Multilinea (. corrisponde newline)
/a.b/m.match("a\nb") # Corrisponde
# x - Free-spacing (ignora spazi bianchi)
pattern = /
\d{3} # prefisso
- # separatore
\d{3} # centrale
- # separatore
\d{4} # numero
/x
# o - Compila una volta (ottimizzazione)
pattern = /\d+/o
Il Trova e Sostituisci di Visual Studio Code (Ctrl/Cmd+H) supporta le regex con potenti capacità di trasformazione. Questa sezione mostra 28 esempi pratici che gli sviluppatori usano ogni giorno.
Accedere a Trova e Sostituisci
Scorciatoie da Tastiera:
- Trova:
Ctrl+F(Windows/Linux) /Cmd+F(Mac) - Sostituisci:
Ctrl+H(Windows/Linux) /Cmd+H(Mac) - Abilita Regex: Clicca il pulsante
.*o premiAlt+R
Suggerimenti:
- Usa
Ctrl+Enter(Cmd+Enter) per sostituire tutto - Anteprima delle corrispondenze prima di sostituire (si evidenziano in giallo)
- Usa
F3/Shift+F3per navigare tra le corrispondenze
Trasformazioni Maiuscole/Minuscole
VS Code supporta sequenze speciali di sostituzione per conversione maiuscole:
| Sequenza | Effetto | Esempio |
|---|---|---|
\l |
Minuscola carattere successivo | \l |
\u |
Maiuscola carattere successivo | \u |
\L |
Minuscola tutti i caratteri seguenti | \L |
\U |
Maiuscola tutti i caratteri seguenti | \U |
\E |
Termina trasformazione maiuscole | \U\E |
Esempio 1: Capitalizza Prima Lettera
Trova:
\b(\w)(\w*)
Sostituisci:
\u$1$2
Prima:
ciao mondo
Dopo:
Ciao Mondo
Questa sezione fornisce oltre 25 pattern regex pronti all'uso.
Validazione Email
^[\w.-]+@[\w.-]+\.[a-z]{2,}$
Numeri di Telefono (Italia)
^(\+?39)?[-.\s]?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$
Date (ISO 8601)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
URL
^https?://(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b
Indirizzi IPv4
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$
Colori Hex
^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
Password Forte
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
Nome Utente (3-16 caratteri)
^[a-zA-Z0-9_-]{3,16}$
UUID v4
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
E altri 15+ pattern con documentazione completa!
Applicazioni regex del mondo reale nello sviluppo.
Validazione Form
const validators = {
email: /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i,
phone: /^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/
};
Estrazione Dati
Estrai email dal testo:
import re
emails = re.findall(r'[\w.-]+@[\w.-]+\.[a-z]{2,}', text)
Parsing Log
pattern = r'(?P<ip>[\d.]+).+(?P<status>\d{3})'
Refactoring Codice
Converti vecchie chiamate API in VS Code:
Trova: apiClient\.get\('([^']+)'\)
Sostituisci: fetch('$1').then(r => r.json())
Errori Comuni
1. Dimenticare di Escapare Caratteri Speciali
❌ Sbagliato: file.txt
✅ Corretto: file\.txt
2. Greedy vs Lazy
❌ Greedy: <.*> corrisponde intero <div>testo</div>
✅ Lazy: <.*?> corrisponde <div> e </div> separatamente
3. Non Usare Ancoraggi
❌ /\d{3}/ corrisponde "123" in "abc123def"
✅ /^\d{3}$/ corrisponde solo esattamente "123"
Suggerimenti Prestazioni
- Usa classi caratteri specifiche invece di
. - Ancora i pattern quando possibile
- Evita quantificatori annidati (backtracking catastrofico)
- Usa gruppi atomici per prestazioni
- Compila i pattern per riutilizzo
Debug
- Testa su regex101.com
- Usa modalità verbose con commenti
- Dividi pattern complessi in parti
- Testa casi limite
Strumenti Online
Tester Regex
- regex101.com - Miglior tester con spiegazioni
- regexr.com - Builder visuale regex
- regexpal.com - Test semplice e veloce
Visualizzatori
- debuggex.com - Diagrammi railroad
- regexper.com - Strumento visuale
Risorse Didattiche
- regexone.com - Lezioni interattive
- regexlearn.com - Guida passo-passo
- regular-expressions.info - Documentazione
Estensioni IDE
- Regex Previewer (VS Code)
- Regex Tester (VS Code)
Classi Caratteri
| Pattern | Corrisponde |
|---|---|
\d |
Cifra [0-9] |
\w |
Word [a-zA-Z0-9_] |
\s |
Spazio bianco |
. |
Qualsiasi carattere |
Quantificatori
| Pattern | Significato |
|---|---|
* |
0 o più |
+ |
1 o più |
? |
0 o 1 |
{n} |
Esattamente n |
Ancoraggi
| Pattern | Significato |
|---|---|
^ |
Inizio riga |
$ |
Fine riga |
\b |
Confine parola |
Flag
| Flag | Significato |
|---|---|
i |
Insensibile maiuscole |
g |
Globale |
m |
Multilinea |
s |
Dotall |
Domande Generali
D: Qual è la differenza tra quantificatori greedy e lazy?
R: Greedy corrisponde al massimo possibile. Lazy (*?, +?) corrisponde al minimo possibile.
D: Come corrispondo a un punto letterale?
R: Escapalo con backslash: \.
D: Cos'è il backtracking catastrofico?
R: Quando la regex prova molte combinazioni, causando lentezza. Evita quantificatori annidati come (a+)+.
D: Le regex possono validare perfettamente un'email?
R: No. Usa regex per formato base, poi verifica via email.
D: Come corrispondo su più righe?
R: Usa il flag s, o usa [\s\S]* invece di .*.
Specifico VS Code
D: Come sostituisco con maiuscole in VS Code?
R: Usa \u (maiuscola successiva), \U (maiuscola tutto).
D: Posso usare regex nella ricerca file di VS Code?
R: Sì! Premi Ctrl+Shift+F e abilita regex (Alt+R).
Estensione Chrome Regex Data Extractor
Il nostro Regex Data Extractor ti aiuta a estrarre dati da pagine web usando i pattern di questa guida.
Funzionalità Chiave
- Libreria Pattern: Pattern pre-costruiti
- Test in Tempo Reale: Testa regex su qualsiasi pagina web
- Esportazione Multi-Formato: CSV, JSON, Excel, PDF
- Estrazione Batch: Estrai da più pagine
Esempio: Estrarre Email
- Installa Regex Data Extractor
- Naviga su qualsiasi pagina web
- Clicca l'icona dell'estensione
- Inserisci pattern:
[\w.-]+@[\w.-]+\.[a-z]{2,} - Clicca "Estrai"
- Esporta in CSV/JSON
Esempio: Estrarre Prezzi
Pattern: €([0-9]{1,3}(?:\.?[0-9]{3})*,?[0-9]{2})
Cattura: €1.234,56, €99,99
Suggerimenti Pro
- Salva pattern usati frequentemente
- Usa gruppi nominati per dati strutturati
- Testa prima i pattern
- Esporta per analisi dati