Backreferences e grupos atômicos

  1. Backreferences
  2. Grupos atômicos

Backreferences

Além do agrupamento, um outro uso dos parênteses é para capturar o texto que casa com a subexpressão que eles envolvem, para que ele possa ser usado depois. Dessa forma, usando backreferences, é possível utilizar o texto que foi lembrado pelos parênteses na mesma expressão regular. Essa funcionalidade está presente em muitas engines.

É possível acessar o texto lembrado pelos parênteses usando a barra invertida e um número, que corresponde à posição do grupo na expressão regular e começa em 1. Exemplos: ([a-z]{2}).\1 (casa com teste e casca), ([a-z])([a-z])\2\1 (casa com assa, osso), ([0-9])[0-9]*\1 (casa com 101, 525 e 942159).

É possível utilizar parênteses apenas para agrupamento sem que a captura seja realizada. Para fazer isso, basta colocar um ?: depois que você abrir parênteses. Exemplos: (?:pr)(e)\1.* (casa com preenchimento e preestabelecido. Veja que a backreference se refere ao segundo grupo, porque no primeiro a captura não é realizada por causa do ?:).

Engines de algumas linguagens, tais como PHP e Python, permitem named captures, que tornam a expressão regular e o código mais claros e legíveis. A sintaxe é (?P<Nome>...). Exemplo: (?P<DDD>\d{2}) (?P<Numero>\d{4,5}-?\d{4}).

Além da presença do named capture deixar a expressão regular mais legível, ela também deixa o código mais legível, pois os grupos são acessados pelo nome fornecido no Python ou no PHP, por exemplo. No Regex 101, não dá para acessar os grupos por seus nomes, mas nas linguagens que suportam named captures, como as que eu citei, dá para fazer isso.

Grupos atômicos

Para entender o que são grupos atômicos, é preciso saber o que é backtracking. No tutorial de quantificadores, esse conceito é explicado. Se você não o conhece, leia esse tutorial antes de prosseguir. Sabendo o que é backtracking, fica fácil entender o que são grupos atômicos. Um grupo atômico é inflexível. Ele não permite que seja feito backtracking nele.

Assim, se houver um ou mais quantificadores gulosos dentro de um grupo atômico que podem ceder caracteres, eles não vão ceder, mesmo se a expressão regular precisar deles para passar. O mesmo vale para a alternação. Não importa quantos branches houver, o branch escolhido não muda.

Grupos atômicos são bem semelhantes aos quantificadores possessivos, inclusive com a mesma vantagem de desempenho que os quantificadores possessivos tem. Para criar grupos atômicos, basta colocar ?> depois de abrir parênteses. Exemplos: (?>.*)e (não casa com nada, já que o quantificador guloso pega todos os caracteres e não devolve nada por estar dentro do grupo atômico), (?>[A-zÀ-ÿ]{4,6}).*es (casa com Camarões. Já (?>[A-zÀ-ÿ]{4,7}).*es não casa com Camarões).