Recursivitate și Apeluri de Subrutine în RegEx ((?R) și (?1)) în Expresii Regulare (RegEx)

Aserțiuni Avansate PCRE (PHP) / Perl / Python (modulul regex)

Ghid complet pentru recursivitate în expresii regulate: parsarea structurilor cu paranteze arbitrar imbricate, apelarea subrutinelor (?1) și depășirea limitelor clasice ale limbajelor regulate.

Tipar RegEx
\((?:[^()]|(?R))*\)

În teoria informaticii teoretice (Ierarhia Chomsky), se învață că limbajele regulate nu pot valida paranteze arbitrar imbricate, deoarece un automat finit nu are memorie pentru a număra adâncimea. Cu toate acestea, motoarele moderne PCRE (PHP preg_match) și modulul regex din Python au depășit această limită prin introducerea Recursivității și a Apelurilor de Subrutine.

Șablonul de aur pentru paranteze arbitrar imbricate: (?R)
\( (?: [^()] | (?R) )* \)

// Unde:
// 1. \( -> Potrivește paranteza deschisă de start.
// 2. (?: ... )* -> Un grup fără captură repetat de oricâte ori.
// 3. [^()] -> Conținut normal care nu este paranteză.
// 4. | (?R) -> MAGIA RECURSIVITĂȚII: apelează din nou ÎNTREAGA expresie regulată!
// 5. \) -> Potrivește paranteza închisă pereche.

// Șiruri potrivite perfect:
// "(a + b)"
// "(a + (b * (c - d)))"  <-- Adâncime de 3 niveluri!
// "(((())))"

Apeluri de Subrutine: Reutilizarea Grupurilor cu (?1)

În loc să recursivăm întreaga expresie, putem refolosi șablonul unui anumit grup de captură definit anterior, evitând duplicarea masivă a expresiilor:

Validarea coordonatelor geografice (X, Y) fără duplicare de cod
# Definim șablonul unei coordonate în grupul 1:
^ ( \d{1,3}\.\d{4,6} ) , \s* (?1) $

# Unde (?1) execută EXACT șablonul definit în grupul 1!
# Nu este un backreference de valoare (nu cere ca numărul să fie identic),
# ci o execuție a aceluiași șablon de validare!

Disponibilitate pe Limbaje

  • PHP: Suport nativ complet în funcțiile preg_* (bazate pe PCRE2).
  • Python: Modulul standard re nu suportă recursivitate; se folosește biblioteca oficială alternativă import regex (instalat prin pip install regex).
  • JavaScript: Nu suportă nativ (?R); pentru structuri adânc imbricate în JS se folosește un parser de tip scanner/lexer manual.