\1 și \k (backreference) în Expresii Regulare (RegEx)

Grupuri și referințe PCRE / ECMAScript / Python

Refolosește în interiorul aceleiași expresii regulare textul exact care a fost capturat anterior de un grup.

Tipar RegEx
(w+)s+1   |   (?<tag>[a-z]+)>.*?</k<tag>>

Ce face \1 și \k<nume> (backreference)

O referință înapoi (backreference) — scrisă \1, \2 (pentru grupuri numerotate) sau \k<nume> (pentru grupuri cu nume) — îi cere motorului RegEx să potrivească exact același text pe care l-a capturat mai devreme grupul respectiv.

Este important să nu confunzi repetarea șablonului cu repetarea valorii capturate: de exemplu, \d\d potrivește orice două cifre (precum 12 sau 99), în timp ce (\d)\1 capturează o cifră și cere ca a doua cifră să fie identică cu prima (potrivind doar 00, 11, 22… 99).

Variante și sintaxă asociată

Expresie / Simbol Descriere
\1, \2, ... \9 Potrivește exact subșirul capturat de grupul 1, 2… în aceeași expresie.
\g{1} sau \g{10} În PCRE (PHP): sintaxă neambiguă pentru backreference (utilă când după ea urmează o cifră).
\k<nume> Backreference către un grup cu nume (?<nume>...) în JS (ES2018+), PHP/PCRE și .NET.
(?P=nume) Backreference către un grup cu nume în Python și PHP/PCRE.

Exemple

Exemplul 1: Detectarea și eliminarea cuvintelor dublate accidental din text

Capturăm un cuvânt în (\b\w+\b) și verificăm dacă după spații urmează exact același cuvânt (\1).

// JavaScript:
const text = "Acesta este este un articol foarte foarte util.";
const corectat = text.replace(/\b(\w+)\s+\1\b/gi, "$1");

Potriviri găsite (Matches)

"Acesta este un articol foarte util."

Exemplul 2: Potrivirea perechilor corecte de ghilimele sau tag-uri HTML cu \k<nume>

Ne asigurăm că ghilimeaua (sau tag-ul) de închidere este identică cu cea de deschidere.

Expresie tag-uri:  /<(?<tag>[a-z][a-z0-9]*)\b[^>]*>.*?<\/\k<tag>>/gi
Expresie ghilimele: /(?<q>['"])(.*?)\k<q>/g
Text:              "<h2>Titlu corect</h2> și <h2>Titlu greșit</h3>"

Potriviri găsite (Matches)

Match 1: "<h2>Titlu corect</h2>"
("<h2>Titlu greșit</h3>" este respins deoarece \k<tag> cere </h2>, nu </h3>!)

Greșeli frecvente

  • Confuzia între \1 (folosit în interiorul expresiei regulare) și $1 (folosit în șirul de înlocuire din replace / preg_replace).
  • În PHP în ghilimele duble "...", secvența "\1" este interpretată de PHP ca caracterul ASCII octal \x01 înainte de a ajunge la RegEx! Scrie întotdeauna expresiile cu backreference în ghilimele simple '...\1...' sau în blocuri nowdoc.

Simboluri și rețete înrudite

  • (...) (grup de captură): Grupează mai multe elemente într-o singură unitate și salvează (capturează) subșirul potrivit pentru extragere sau înlocuire.
  • (?<nume>...) (grup cu nume): Asociază un nume descriptiv unui grup de captură pentru a accesa valoarea extrasă după cheie, nu doar după număr.
  • \b și \B (limită de cuvânt): Potrivește poziția de graniță dintre un cuvânt și un non-cuvânt (\b) sau o poziție din interiorul cuvântului (\B).
  • Greedy vs Lazy (*?, +?, ??): Controlează dacă un cuantificator consumă cât mai mult text posibil (greedy) sau cât mai puțin (lazy / non-greedy).