Regex: Flag sticky "y", busca em posição específica
O JavaScript oferece ferramentas poderosas para manipulação de strings, e entre elas, a flag sticky (y) em expressões regulares ocupa um lugar especial.
A flag y — a flag sticky — é uma das flags que você pode adicionar a uma expressão regular JavaScript. Ela ancora cada busca a uma posição exata: o lastIndex da expressão regular. Se uma correspondência não puder começar exatamente em lastIndex, a correspondência falha — o motor não avança para procurar uma correspondência em outro lugar.
Esta página aborda o que a flag sticky faz, como ela difere da flag global (g), como lastIndex é lido e atualizado, as armadilhas comuns, e onde a flag é genuinamente útil (tokenizadores e parsers sequenciais).
O Conceito da Flag Sticky (y)
A flag sticky (y) garante que a correspondência comece exatamente no índice armazenado na propriedade lastIndex do objeto de expressão regular. Esse é o contraste principal com a flag global (g): g permite que o motor avance a partir de lastIndex para encontrar a próxima correspondência em qualquer ponto posterior da string, enquanto y exige que a correspondência comece em lastIndex ou não ocorra de forma alguma. Esse comportamento de "não avançar" é exatamente o que um tokenizador precisa — ele garante que a entrada seja consumida de forma contígua, sem lacunas inesperadas entre os tokens.
y não avança — g avança
A maneira mais clara de ver a diferença é fornecer a ambas as flags um padrão que não corresponda na posição 0:
A flag g encontra abc mesmo que ela comece no índice 3. A flag y retorna null, porque a posição 0 contém um ., não o início de abc.
No exemplo acima, a flag y garante que a segunda chamada a test comece a corresponder na posição imediatamente após a correspondência anterior. Dois detalhes merecem atenção:
- Uma correspondência bem-sucedida avança
lastIndexpara o índice logo após a correspondência (0 → 3 → 6). Esse avanço automático é o que permite chamartest/execem um loop. - Uma correspondência falha redefine
lastIndexpara 0. Após a terceira chamada retornarfalse,lastIndexvolta a 0, pronto para recomeçar.
lastIndex é lido e gravado
lastIndex não é apenas uma entrada que você define — o motor o atualiza a cada chamada de test/exec que usa y (ou g). Portanto, o padrão normal é: defina lastIndex uma vez se quiser começar em algum lugar diferente de 0, e então deixe o loop gerenciá-lo.
Sticky também afeta âncoras
Com a flag y, a âncora de início de string ^ não é reancorада em lastIndex — ^ ainda significa "início de toda a string" (ou início de uma linha com a flag m). O comportamento sticky vem da regra implícita "corresponder em lastIndex", não de reescrever ^. Portanto, um padrão como /^x/y falhará em qualquer lastIndex maior que 0, porque ^ nunca pode ser satisfeito lá.
Aplicações Práticas da Flag Sticky
Analisando Fluxos de Dados
A flag sticky é particularmente vantajosa ao analisar fluxos de dados onde você precisa corresponder tokens sequencialmente.
Tokenizando Strings
Outro caso de uso comum é tokenizar strings onde você precisa garantir que o tokenizador avance de uma correspondência para a próxima sem pular nenhum caractere.
Buscando em uma Posição Específica
A propriedade lastIndex do JavaScript combinada com a flag sticky pode ser usada para buscar padrões a partir de uma posição específica em uma string.
Neste exemplo, definir lastIndex como 6 permite que o método test encontre a palavra "world" a partir da posição especificada.
Combinando a Flag Sticky com Outras Flags
A flag sticky pode ser combinada com outras flags, como g (global), para aprimorar as capacidades de correspondência de padrões. Neste exemplo, a flag g permite uma busca global por toda a string, enquanto a flag y garante que cada correspondência comece exatamente na posição lastIndex. Essa combinação permite realizar uma busca global com o comportamento de correspondência sequencial estrita da flag sticky.
Neste exemplo, atualizamos a regex para consumir o delimitador de vírgula. Isso garante que a próxima correspondência comece na posição correta sem manipulação manual do índice.
Exemplos Avançados
Extraindo Pares Chave-Valor
Considere um cenário mais complexo onde você precisa extrair pares chave-valor de uma string com vários separadores. Cada parte do par é extraída com um grupo de captura — match[1] é a chave e match[3] é o valor.
Analisando Logs
A flag sticky pode ser extremamente útil ao analisar logs estruturados onde as entradas devem ser correspondidas a partir de posições específicas.
Observe que o grupo de mensagem é [^;]+ ("tudo até o próximo ;") em vez de \w+. Com \w+, uma mensagem contendo um espaço interromperia a correspondência no meio da entrada; como a flag sticky se recusa a avançar, o próximo exec falharia e o loop encerraria cedo — descartando silenciosamente as entradas restantes. Essa é a armadilha mais comum da flag sticky: seu padrão deve consumir a entrada de forma contígua, ou a análise para abruptamente.
Quando usar y (e quando não usar)
Use a flag sticky quando:
- Você está escrevendo um tokenizador ou parser e precisa consumir a entrada de forma contígua, um token por vez, sem lacunas permitidas.
- Você deseja verificar se um padrão corresponde em uma posição exata, sem que o motor vague para encontrar uma correspondência mais adiante na string.
Prefira a flag global simples (g) quando você simplesmente deseja todas as correspondências em qualquer lugar da string e não se importa se são adjacentes — por exemplo, encontrar todos os endereços de email em um documento.
Lembre-se das duas regras que causam a maioria dos bugs com a flag sticky: uma correspondência falha redefine lastIndex para 0, e seu padrão deve consumir cada caractere entre as correspondências ou o loop para cedo.
Conclusão
A flag sticky (y) troca a conveniência de "buscar em qualquer lugar" do g por uma correspondência estrita, bloqueada na posição lastIndex. Essa troca é exatamente o que você deseja ao construir tokenizadores e parsers sequenciais, onde o consumo contíguo importa. Combine-a com grupos de captura para extrair dados estruturados, e fique atento ao lastIndex — uma vez que você entende como ele avança e redefine, a correspondência sticky se torna uma ferramenta precisa e previsível.
Tópicos Relacionados
- Padrões e flags
- Âncoras: início
^e fim$de string - Grupos de captura
- Expressões regulares em JavaScript