Regex é uma linguagem universal. Podemos usar a sintaxe dela nas mais diversas linguagens de programação e inclusive em outros ambientes como no ambiente do Excel ou da linha de comando de sistemas operacionais. A mesma regex pode ser usada tanto em Python quanto em Java quanto em JavaScript quanto em C# quanto no Excel, etc.
Por terem sintaxe própria, devemos aprender mais sobre os metacaracteres característicos da linguagem de regex. Nesta parte 2, vou introduzir um pouco os metacaracteres.
Antes de iniciar, como dito na parte 1, vou usar Python para brincar com regex por aqui mas querendo abstrair o máximo possível de Python pra focar o máximo possível em regex, então resolvi criar uma função em Python para verificar regex em textos, que será esta:
def regex(padrao, texto):
import re
pattern = re.compile(r'{}'.format(padrao))
test_match = re.search(pattern, texto)
if test_match:
print('Deu match!')
matches = pattern.finditer(texto)
for match in matches:
print(f'Achei a regex "{padrao}" no texto entre as posições {match.span()[0]} e {match.span()[1]}')
print(f'Match = {match.group()}')
else:
print('Não deu match! :(')
Não precisam se preocupar com o que tá aí, mas a partir de agora ao verificar uma expressão regular, só vou chamar a função e passar o padrão e o texto como argumentos da função.
Então, dando início, vamos falar de metacaracteres. Os metacaracteres são caracteres intrínsecos à sintaxe de regex e cada um tem uma função:
. ^ $ * + ? { } [ ] \ | ( )
Iremos ver o significado de cada metacaractere no decorrer dos tópicos.
Em regex a gente sempre tá igual ao usuário do aplicativo Tinder: procurando um match. Passamos um padrão e procuramos matches dentro de um texto. O primeiro metacaractere a ser falado é o ponto (.). O ponto casa com tudo. Ele não se importa se meu texto tem letras, números, arrobas, interrogações, pontos finais, etc, ele casa simplesmente com tudo:
texto_1 = 'bastter.com'
padrao = '.'
regex(padrao, texto_1)
E o resultado é o seguinte:
Deu match!
Achei a regex "." no texto entre as posições 0 e 1
Match = b
Achei a regex "." no texto entre as posições 1 e 2
Match = a
Achei a regex "." no texto entre as posições 2 e 3
Match = s
Achei a regex "." no texto entre as posições 3 e 4
Match = t
Achei a regex "." no texto entre as posições 4 e 5
Match = t
Achei a regex "." no texto entre as posições 5 e 6
Match = e
Achei a regex "." no texto entre as posições 6 e 7
Match = r
Achei a regex "." no texto entre as posições 7 e 8
Match = .
Achei a regex "." no texto entre as posições 8 e 9
Match = c
Achei a regex "." no texto entre as posições 9 e 10
Match = o
Achei a regex "." no texto entre as posições 10 e 11
Match = m
Visualizando isso de outra forma usando o site regexpal:

Percebam que tivemos 11 matches, ou seja, o ponto casou com todos os caracteres, inclusive o próprio ponto de "bastter.com". Caso eu queira capturar somente o ponto de "bastter.com", preciso "escapar" o ponto.
Ou seja, todos os metacaracteres acima vistos têm alguma função em expressões regulares, mas pode ser que em algum momento seja necessário eu capturar algum desses caracteres num texto, então para isso eu preciso escapar esse caractere usando uma contrabarra (\). Vamos capturar agora o ponto de bastter.com:
texto_1 = 'bastter.com'
padrao = '\.'
regex(padrao, texto_1)
Resultado:
Deu match!
Achei a regex "\." no texto entre as posições 7 e 8
Match = .
No regexpal:

Deu pra ver como é a correlação da saída do resultado da avaliação da regex com Python com o resultado do regexpal. Agora vou usar mais o Python e o regexpal só de vez em quando.
Acabamos de ver a função do ponto, que é casar com tudo que ele vê pela frente. O raciocínio a partir de agora vai ser esse, se precisamos casar algum metacaractere com o texto, precisamos escapar esse caractere com uma contrabarra:
texto_1 = '[12345]'
padrao = '\['
regex(padrao, texto_1)
Resultado:
Deu match!
Achei a regex "\[" no texto entre as posições 0 e 1
Match = [
O ponto casa com tudo, mas no tópico passado usamos outra regex que casou com todo nosso texto, que foi "\w". O "\w" casa com todas as letras:
texto_1 = 'bastter.com'
padrao = '\w'
regex(padrao, texto_1)
Resultado:
Deu match!
Achei a regex "\w" no texto entre as posições 0 e 1
Match = b
Achei a regex "\w" no texto entre as posições 1 e 2
Match = a
Achei a regex "\w" no texto entre as posições 2 e 3
Match = s
Achei a regex "\w" no texto entre as posições 3 e 4
Match = t
Achei a regex "\w" no texto entre as posições 4 e 5
Match = t
Achei a regex "\w" no texto entre as posições 5 e 6
Match = e
Achei a regex "\w" no texto entre as posições 6 e 7
Match = r
Achei a regex "\w" no texto entre as posições 8 e 9
Match = c
Achei a regex "\w" no texto entre as posições 9 e 10
Match = o
Achei a regex "\w" no texto entre as posições 10 e 11
Match = m
Vejam que minha regex casou com todas as letras, mas não casou com o ponto. Confirmamos que "\w" casa com caracteres que representam letras. Vamos tentar casar com um número de CPF:
texto_1 = '123.456.789-10'
padrao = '\w'
regex(padrao, texto_1)
Resultado:
Deu match!
Achei a regex "\w" no texto entre as posições 0 e 1
Match = 1
Achei a regex "\w" no texto entre as posições 1 e 2
Match = 2
Achei a regex "\w" no texto entre as posições 2 e 3
Match = 3
Achei a regex "\w" no texto entre as posições 4 e 5
Match = 4
Achei a regex "\w" no texto entre as posições 5 e 6
Match = 5
Achei a regex "\w" no texto entre as posições 6 e 7
Match = 6
Achei a regex "\w" no texto entre as posições 8 e 9
Match = 7
Achei a regex "\w" no texto entre as posições 9 e 10
Match = 8
Achei a regex "\w" no texto entre as posições 10 e 11
Match = 9
Achei a regex "\w" no texto entre as posições 12 e 13
Match = 1
Achei a regex "\w" no texto entre as posições 13 e 14
Match = 0
Ou seja, o "\w" casa tanto com letras como com números. Vamos conferir isso no regexpal:

Vejam que a regex casou com os números mas ignorou os pontos e o traço. Ou seja, a regex "\w" casa com tudo que é caractere que represente uma letra ou um número.
Entretanto, não sabemos ainda como capturar um número de CPF inteiro ou uma URL como bastter.com inteira de forma seletiva, pois a regex "." casa com tudo e a "\w" casa somente com letras e números. Iremos usar mais metacaracteres para descobrir como casar com textos específicos como URLs e números de CPF, números de telefone, nomes próprios, etc, nos tópicos seguintes.