DanLevy.net

Quiz: Padronanza delle espressioni regolari

Riesci a domare qualche espressione regolare selvaggia?

Pronto a lottare con alcune Espressioni Regolari? 🤼‍♂️

Metti alla prova la tua conoscenza delle RegEx con domande che coprono pattern di base, quantificatori, gruppi e quelle insidiose asserzioni look‑around. Dalla semplice corrispondenza di stringhe alla complessa validazione di pattern – riesci a individuare la regex corretta?

Cosa corrisponde?

'cat CAT Cat'.match(/cat/g)

Questo pattern usa g, ma non i:

  • g trova tutte le corrispondenze
  • Senza i, il matching è sensibile al caso

Senza il flag i, solo “cat” in minuscolo corrisponde.

È particolarmente utile quando si gestiscono input utente o HTML dove il caso può variare.

Scopri di più sui flag RegExp

Cosa restituirà questo codice?

const words = ['cat', 'hat', 'what', 'bat'];
words.filter(word => word.match(/^[ch]at/))

Il pattern /^[ch]at/ corrisponde alle stringhe che:

  • Iniziano (^) con ‘c’ o ‘h’ (ecco cosa significa [ch] – una classe di caratteri che accetta un solo carattere)
  • Sono seguite letteralmente da ‘at’

Pertanto, solo “cat” e “hat” soddisfano questo pattern. Il metodo filter() conserva solo gli elementi corrispondenti.

Maggiori informazioni sulle classi di caratteri su MDN

Cosa corrisponderà questo?

'<div>Hello</div><div>World</div>'.match(/<div>.*?<\/div>/g)

Il pattern /<div>.*?<\/div>/g utilizza il matching non‑greedy con *?, che significa:

  • Corrispondi <div>
  • Corrispondi qualsiasi carattere (.*) ma il meno possibile (?)
  • Fino a trovare </div>
  • Il flag g fa sì che vengano trovate tutte le occorrenze

Senza il ?, il greedy .* corrisponderebbe a tutto, dal primo <div> all’ultimo </div>, producendo un’unica corrispondenza grande. Con ?, corrisponde a ciascuna coppia separatamente.

Scopri di più sul matching greedy vs lazy

Cosa restituirà?

'hello\nworld'.match(/\w+/g)

Il pattern \w+ corrisponde a uno o più caratteri di parola. Anche se nella stringa c’è un newline, \w corrisponde a:

  • Lettere (a-z, A-Z)
  • Numeri (0-9)
  • Underscore (_)

Quindi il newline funge da confine di parola, e otteniamo due corrispondenze. Se avessimo usato .*, non corrisponderebbe al newline per impostazione predefinita (servirebbe il flag s per farlo).

Scopri di più sui metacaratteri

Cosa corrisponderà questo?

'$100 and €50'.match(/\d+(?=[\$€])/g)

Questo pattern non trova corrispondenze perché controlla i simboli di valuta dopo le cifre, mentre nell’input le precedono. Se vuoi cifre precedute da $ o €, usa un look-behind: /(?<=[\$€])\d+/g.

I look-ahead controllano cosa viene dopo la posizione corrente. Il pattern così scritto cerca:

  • Una o più cifre (\d+)
  • Seguite da ((?=...)) oppure $ o € ([\$€])

Poiché non ci sono numeri seguiti da simboli di valuta (sono preceduti da essi), non otteniamo corrispondenze.

Scopri di più sulle asserzioni look-ahead

Cosa corrisponderà?

'cat cats category'.match(/\bcat\b/g)

Il \b rappresenta un confine di parola, che corrisponde:

  • Tra un carattere di parola e un carattere non‑parola
  • All’inizio/fine della stringa se c’è un carattere di parola

Quindi /\bcat\b/ corrisponde a “cat” solo quando è una parola completa, non parte di un’altra parola.

  • ✅ “cat” (circondato da spazi)
  • ❌ “cats” (nessun confine dopo “cat”)
  • ❌ “category” (nessun confine dopo “cat”)

Scopri di più sui confini di parola

Qual è l’output?

'banana'.match(/a/g)

Il flag g (global) cambia il comportamento di match():

  • Senza g: restituisce la prima corrispondenza con i gruppi di cattura
  • Con g: restituisce un array di tutte le stringhe corrispondenti

In questo caso, trova tutte le occorrenze di “a” in “banana”.

Nota: se ti servono sia tutte le corrispondenze CHE i gruppi di cattura, usa matchAll() o il metodo exec() in un ciclo.

Scopri di più sul flag globale

Cosa corrisponde a questo modello?

'abc123 def456'.match(/(?<!abc)\d+/g)

Il look-behind negativo (?<!abc) garantisce che le cifre non siano precedute da “abc”:

  • ❌ “123” (preceduto da “abc”)
  • ✅ “23” (preceduto da “abc1”)
  • ✅ “456” (preceduto da “def”)

JavaScript supporta le asserzioni look-behind nei motori moderni. Questo esempio usa un look-behind a lunghezza fissa: abc è sempre di tre caratteri. Il look-behind a lunghezza variabile è l’aspetto più complicato e dipende dal motore.

Nota: il supporto al look-behind è relativamente recente in JavaScript. Controlla la compatibilità del browser se devi supportare browser più vecchi.

Cosa restituirà?

'2029-12-31'.match(/(\d{4})-(\d{2})-(\d{2})/).slice(1)

Il pattern utilizza tre gruppi di cattura:

  1. (\d{4}) cattura l’anno
  2. (\d{2}) cattura il mese
  3. (\d{2}) cattura il giorno

match() senza il flag g restituisce:

  • Indice 0: Corrispondenza completa
  • Indice 1+: Gruppi di cattura

slice(1) è un trucco comune per ottenere solo i gruppi di cattura.

Maggiori informazioni su gruppi e cattura

Quale sarà il risultato di questo?

"123aBc".match(/^\d+(?![a-z])/ig)

Il flag i rende [a-z] valido per lettere ASCII sia maiuscole sia minuscole. Il quantificatore greedy \d+ prova prima 123, ma il look-ahead fallisce davanti ad a. Il motore torna indietro a 12: il carattere successivo è 3, non una lettera, quindi la corrispondenza riesce.

Approfondisci il look-ahead negativo

Cosa restituisce?

'a,b,c'.split(/(?<=,)/)

Il pattern /(?<=,)/ è un look-behind che corrisponde dopo una virgola:

  • a, (dopo la virgola)
  • b, (dopo la virgola)
  • c (nessuna virgola dopo)

Il look-behind non consuma la virgola, quindi la virgola rimane collegata al segmento precedente nel risultato dello split.

Questo è utile quando vuoi dividere una stringa in base a ciò che la precede senza perdere il(i) carattere(i) di split.

Scopri di più sulle asserzioni look-behind

Cosa corrisponde?

'$100'.match(/$\d+/)

I caratteri speciali devono essere escapati con \\ per corrispondere letteralmente:

  • $ è un carattere speciale (fine della stringa)
  • Per corrispondere a un segno di dollaro letterale, escapalo: \\$

Caratteri comuni che necessitano di escape:

. * + ? ^ $ [ ] \ ( ) { } |

Senza escape, molti caratteri speciali hanno significati regex che potrebbero non essere quelli desiderati.

Scopri di più su come escapare i caratteri speciali

Cosa viene abbinato?

'$100'.match(/(?<=\$)\d+/)

Il look-behind positivo (?<=\$) assicura che le cifre siano precedute da un simbolo di dollaro:

  • (?<=\$): Look-behind per il simbolo di dollaro
  • \d+: Corrisponde a una o più cifre

Le asserzioni look-behind non consumano caratteri; controllano solo ciò che precede. È utile quando vuoi abbinare qualcosa in base a ciò che lo precede senza includere la parte precedente.

Scopri di più sulle asserzioni look-behind

Cosa viene abbinato?

'<b>bold</b>'.match(/<b>(.*?)<\/b>/).slice(1)

Il pattern utilizza il matching lazy con *?:

  • <b>: corrisponde al tag di apertura
  • (.*?): cattura qualsiasi carattere (lazy)
  • </b>: corrisponde al tag di chiusura

Il ? dopo * lo rende lazy, abbinando il minor numero possibile di caratteri. Senza ? sarebbe greedy e abbinerebbe il più possibile.

slice(1) restituisce solo il gruppo catturato.

Scopri di più su greedy vs lazy matching

Cosa corrisponde?

'😀 🙂'.match(/\p{Emoji}/gu)

Il flag u abilita:

  • le escape di proprietà Unicode (\p{...})
  • la corretta gestione delle coppie surrogate

Il flag u abilita la modalità Unicode; nei motori moderni anche v abilita una modalità Unicode con funzionalità aggiuntive. Il pattern \p{Emoji} corrisponde ai caratteri con la proprietà Unicode Emoji. In questa stringa, ciò significa i due pittogrammi emoji.

Nota: le escape di proprietà Unicode richiedono la modalità Unicode, attivata con u oppure v.

Approfondisci la modalità Unicode

Scusate in anticipo! 😈
Quale password corrisponde a questo pattern?

/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/

Non scrivete nulla del genere in produzione! 😅

Questo pattern utilizza più look-ahead positivi per imporre:

  • Almeno una lettera maiuscola: (?=.*[A-Z])
  • Almeno una lettera minuscola: (?=.*[a-z])
  • Almeno una cifra: (?=.*\d)
  • Almeno un carattere speciale: (?=.*[!@#$%^&*])
  • Lunghezza minima di 8: .{8,}

I look-ahead sono perfetti per la validazione delle password perché possono verificare più criteri senza consumare caratteri.

Scopri di più sui pattern di validazione delle password

Come è andata? 🧐

Le espressioni regolari possono essere una bestia da domare, ma sono incredibilmente potenti una volta che le prendi in mano (e tutta la sintassi più recente). Continua a esercitarti, e diventerai un maestro di RegEx in men che non si dica! 🧙‍♂️

Cerchi una pausa dopo tutto quel RegEx?
Pftt, ricorda: pausa dopo le competenze!

Vai al la mia palestra per affrontare altre sfide! 💪