C#  -  Usando Regex (revisitado)


 Hoje vamos recordar como criar expressões regulares e como elas podem ser aplicadas para resolver alguns problemas comuns.

Um regex é um padrão que descreve uma string através do uso de caracteres especiais que denotam um trecho de texto específico para corresponder. O uso de regex não é um conceito novo em programação e para ele funcione, é preciso usar um mecanismo de regex que faça todo o trabalho pesado.


Para usar regex, precisamos importar o assembly System.Text.RegularExpressions para seu projeto. Isso vai permitir que o compilador use o padrão regex e o aplique ao texto específico que você precisa.

Vejamos um exemplo básico usando uma aplicação Console (.NET Core) no .NET 6:

Classe Exemplo1.cs

using System.Text.RegularExpressions;

namespace CRegex;

public class Exemplo1
{
    public void ValidaData(string stringAValidar)
    {
        string padrao1 = $@"^(19|20)\d\d[-./](0[1-9]|1[0-2]|[1-9])[-./](0[1-9]|[12][0-9]|3[01])$";

        if (Regex.IsMatch(stringAValidar, padrao1))
        {
            Console.WriteLine($"A string {stringAValidar} contém uma data válida.");
        }
        else
        {
            Console.WriteLine($"A string {stringAValidar} NÃO Contém uma data válida.");
        }
    }
}

Definimos um padrão Regex - padrao1 - para validar uma Data e usamos o método IsMatch que vai indicar se a expressão regular encontra uma correspondência na cadeia de caracteres de entrada.

Para testar vamos definir o código a seguir na classe Program:

using CRegex;

Exemplo1 exemplo = new Exemplo1();

exemplo.ValidaData("1912-12-31");
exemplo.ValidaData("2018-01-01");
exemplo.ValidaData("1800-01-21");

exemplo.ValidaData($"{DateTime.Now.Year}.{ DateTime.Now.Month }.{ DateTime.Now.Day}");

exemplo.ValidaData("2016-21-12");

Console.ReadLine();

 

O resultado obtido é o seguinte:

Vejamos a seguir os símbolos usados na expressão padrão definida no exemplo:

| O condicional OR                                
(19|20) Permite somente 19 e 20
\d\d Faz a correspondência de dois dígitos entre 0 e 9. Para corresponder apenas um dígito entre 0 e
9, você usaria \d.
[-./] Corresponde a qualquer um dos seguintes caracteres no conjunto de caracteres.
0[1-9] Corresponde a qualquer parte começando com zero seguido por qualquer dígito entre 1 e 9. Isso corresponderá a 01, 02, 03, 04, 05, 06, 07, 08 e 09
[1-9] Corresponde a qualquer dígito entre 1 e 9
[12][0-09]  Corresponde a qualquer parte começando com 1 ou 2, seguido por qualquer dígito entre 0 e 9. Corresponderá a todas as cadeias de números entre 10 e 29
3[01] Corresponde a qualquer parte começando com 3 e seguido por 0 ou 1. Isso corresponderá a 30 ou 31.
^ Diz ao mecanismo regex para iniciar no início da string fornecida para corresponder.
$ Diz ao mecanismo regex para parar no final da string fornecida para corresponder

Assim a expressão Regex que definirmos será interpretada da seguinte forma:

Vejamos agora outro exemplo que podemos aplicar quando desejamos filtrar a entrada de dados. Isso pode ser útil para evitar a injeção SQL ou assegurar que uma URL informada é válida, ou evitar que certas palavras sejam exibidas em um texto.

Vamos definir uma lista de strings que fazem parte de uma lista negra de palavras para filtrar as palavras em texto.

Naturalmente existem outras formas mais elegantes de realizar esta tarefa mas vai servir como um exemplo prático de usar Regex.

Vamos criar a classe Filtro com o seguinte código:

using System.Text.RegularExpressions;

namespace CRegex;

public class Filtro
{
    public string Validar(string input)
    {
        List<string> listaNegra = new List<string>(new string[] { "insulto1", "insulto2", "insulto3" });
        string padrao = "";

        foreach (string palavra in listaNegra)
        {
            padrao += padrao.Length == 0 ? $" {palavra}" : $"| { palavra} ";
        }

        padrao = $@"\b({padrao})\b";

        return Regex.Replace(input, padrao, "#####", RegexOptions.IgnoreCase);
    }
}

Aqui definimos o regex que vamos usar para procurar as palavras na lista negra.

Vamos concatenar as palavras com o caractere | (OR) para que o regex corresponda a qualquer das palavras, e quando a lista estiver completa, vamos anexar a expressão \b ao lado do regex. Isso denota um limite de palavras e, portanto, só vai corresponder às palavras que forem exatamente iguais.

A seguir vamos usar o método Regex.Replace() que recebe a entrada e procura a ocorrência das palavras definidas no padrão, ignorando maiúsculas e substituindo os insultos com #####.

Para testar vamos definir o código abaixo na classe Program:

using CRegex;

Filtro filtro1 = new Filtro();

string texto = "Este é um exemplo de uma string que contém um insulto1, dois insulto2
                      e três insulto3 que são palavras ofensivas";

texto = filtro1.Validar(texto);

Console.WriteLine("Texto após validação\n");
Console.WriteLine(texto);

Console.ReadLine();

O resultado obtido será:

A seguir temos exemplos de algumas expressões regulares que podemos usar :

Validar

Expressão Regular
Email ^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$   ou   ^\\S+@\\S+\\.\\S+$ (validar formato)  
IPv4  ^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
Cep ^[0-9]{5}(?:-[0-9]{4})?$
Telefone ^[0-9]{2}-[0-9]{4}-[0-9]{4}$ ou  ^\\+?[1-9][0-9]{7,14}$
Data (dd/mm/yyyy) ^((0[1-9]|[12]\d)\/(0[1-9]|1[0-2])|30\/(0[13-9]|1[0-2])|31\/(0[13578]|1[02]))\/\d{4}$ ou ^([0]?[1-9]|[1|2][0-9]|[3][0|1])[./-]([0]?[1-9]|[1][0-2])[./-]([0-9]{4}|[0-9]{2})$  ou  ^[0-9]{1,2}\\/[0-9]{1,2}\\/[0-9]{4}$
URL ^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$
CPF ^(\d{3}.\d{3}.\d{3}-\d{2})|(\d{11})$ ou ^\d{3}\x2E\d{3}\x2E\d{3}\x2D\d{2}$
CNPJ ^\d{3}.?\d{3}.?\d{3}/?\d{3}-?\d{2}$ ou ^\d{2}\.\d{3}\.\d{3}\/\d{4}\-\d{2}$
Somente números ^[0-9]*$ ou  ^\\d+$"
Senha ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$ ( 8 caracteres, uma caixa alta, uma caixa baixa, um digito, um caractere especial)

Significado dos caracteres e expressões usadas :

Você pode procurar por expressões regulares no link: http://regexlib.com/Search.aspx

E estamos conversados.

"Esta é a vida eterna: que te conheçam, o único Deus verdadeiro, e a Jesus Cristo, a quem enviaste"
João 17:3

Referências:


José Carlos Macoratti