Muito bom, só gostaria de acrescentar uns detalhes...
Acho importante falar que existem diferenças entre as linguagens, cada uma implementa regex de um jeito e o que vale pra uma pode não funcionar em outra. Claro que muitas coisas funcionam igual, mas tem várias diferenças também.
Por exemplo, os separadores (que também podem ser chamados de delimitadores) que vc citou valem pra PHP e Perl, mas em JavaScript só se usa as barras (/regex aqui/
). Em outras linguagens, como Java, Python e C#, se passa uma string contendo a regex, mas sem os delimitadores (ex: em Python se faz apenas re.search('[a-z]', texto)
- se usar re.search('/[a-z]/', texto)
, ele vai procurar pelas barras no texto).
Muitas linguagens suportam Unicode por padrão, então atalhos como \w
consideram todas as letras definidas pelo Unicode, o que inclui vários alfabetos como o japonês, coreano, árabe, cirílico, etc. E também considera os dígitos Unicode (não é só de 0 a 9, tem vários outros caracteres).
Em Python 3, por exemplo, o \w
já suporta Unicode por padrão. Em PHP precisa usar a flag u
, no JavaScript essa flag não adianta e precisa de Unicode property escapes (ex: /\p{L}/u
para letras), em Java a flag que habilita o modo Unicode é Pattern.UNICODE_CHARACTER_CLASS
, etc. Cada linguagem pode ou não suportar Unicode, que pode ou não ser o default, e pode ou não ter modos de configurar.
Um detalhe importante que muita gente esquece - inclusive eu - é que o \w
(minúsculo) também considera o caractere _
. Então \W
(maiúsculo) na verdade é tudo que não for letra, número, ou _
.
Quanto as flags, também tem diferenças. A flag g
, por exemplo, é coisa do JavaScript. Em outras linguagens o normal é procurar todas as ocorrências, enquanto outras fornecem opções diferentes para cada caso. Por exemplo, em Python usa-se match
ou search
para buscar uma ocorrência e findall
ou finditer
para buscar todas. Em PHP usa-se preg_match
para a primeira ocorrência e preg_match_all
para todas, em Java faz-se um loop no objeto Matcher
(controlando a quantidade de vezes, caso não queira todas) e assim por diante. Ou seja, nessas linguagens não precisa da flag g
.
E a forma de ligar as flags também muda. Nas linguagens que possuem delimitadores (JavaScript, PHP, Perl), coloca-se no final (/\w/img
por exemplo), em outras coloca-se como parâmetros (exemplo em Python: re.compile(r'\w', re.I)
para passar a flag case insensitive).
Já o \X
é mais do que "qualquer caractere Unicode". Na verdade ele corresponde a um grapheme cluster. De forma bem resumida, muitos caracteres na verdade são formados por vários code points que juntos representam uma coisa só. Um exemplo moderno são as sequências de emojis, mas muitos idiomas possuem caracteres que só podem ser representados por mais de um code point - leia aqui, aqui e aqui para mais informações.
O problema é que nem todas as engines suportam o \X
, e mesmo quando suportam, ele pode não reconhecer todos os grapheme clusters, pois depende da versão do Unicode suportada.
Quanto a ^
e $
, que indicam o início e fim da string, vale lembrar que muitas engines possuem a flag multiline. Quando habilitada, esses atalhos também pegam o início e fim de uma linha. Já o \A
e \Z
pegam só o início e fim da string, independente da flag estar habilitada.
E algumas engines também suportam o \z
, que tem diferença quando a string termina com uma quebra de linha (\Z
vai até a quebra de linha e não a inclui no match, \z
vai até o final e inclui a quebra de linha).