---
title: "Pattern Matching e Regex em Zig — Bibliotecas e Técnicas"
url: "https://ziglang.com.br/ecossistema/pattern-matching-e-regex-em-zig-bibliotecas-e-t%C3%A9cnicas/"
markdown_url: "https://ziglang.com.br/ecossistema/pattern-matching-e-regex-em-zig-bibliotecas-e-t%C3%A9cnicas.MD"
description: "Guia de pattern matching em Zig: expressões regulares, compilação comptime, bibliotecas de regex, parsing e técnicas de busca textual."
date: "2026-02-21"
author: "Zig Brasil"
---

# Pattern Matching e Regex em Zig — Bibliotecas e Técnicas

Guia de pattern matching em Zig: expressões regulares, compilação comptime, bibliotecas de regex, parsing e técnicas de busca textual.


# Pattern Matching e Regex em Zig — Bibliotecas e Técnicas

O Zig aborda pattern matching de forma pragmática. Embora a biblioteca padrão não inclua um motor de expressões regulares completo (por questões de tamanho e complexidade), o ecossistema oferece múltiplas opções: desde bibliotecas nativas em Zig até bindings para PCRE2. Além disso, as capacidades de comptime do Zig permitem compilar padrões em tempo de compilação para performance máxima.

## Busca de Strings na Biblioteca Padrão

O `std.mem` oferece funções eficientes para busca e manipulação de strings:

```zig
const std = @import("std");
const mem = std.mem;

pub fn main() void {
    const texto = "O Zig é uma linguagem de programação incrível";

    // Buscar substring
    if (mem.indexOf(u8, texto, "linguagem")) |pos| {
        std.debug.print("'linguagem' encontrada na posição {}\n", .{pos});
    }

    // Verificar prefixo e sufixo
    const comeca = mem.startsWith(u8, texto, "O Zig");
    const termina = mem.endsWith(u8, texto, "incrível");
    std.debug.print("Começa com 'O Zig': {}\n", .{comeca});
    std.debug.print("Termina com 'incrível': {}\n", .{termina});

    // Contar ocorrências
    const count = mem.count(u8, texto, "a");
    std.debug.print("Ocorrências de 'a': {}\n", .{count});

    // Substituir
    var buf: [256]u8 = undefined;
    const resultado = mem.replace(u8, texto, "incrível", "fantástica", &buf);
    std.debug.print("Substituído: {s} ({} substituições)\n", .{ buf[0..resultado], resultado });

    // Split
    var iter = mem.splitSequence(u8, texto, " ");
    while (iter.next()) |palavra| {
        std.debug.print("Palavra: {s}\n", .{palavra});
    }

    // Trim
    const com_espacos = "  Olá, mundo!  ";
    const trimmed = mem.trim(u8, com_espacos, " ");
    std.debug.print("Trimmed: '{s}'\n", .{trimmed});
}
```

## zig-regex — Regex Nativa em Zig

A biblioteca zig-regex implementa um motor de expressões regulares em Zig puro:

```zig
const regex = @import("zig-regex");

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    // Compilar padrão
    var re = try regex.Regex.compile(allocator, "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
    defer re.deinit();

    // Testar match
    const texto = "Contato: maria@exemplo.com ou suporte@empresa.com.br";

    if (try re.match(texto)) |m| {
        std.debug.print("Email encontrado: {s}\n", .{m.slice});
    }

    // Encontrar todas as ocorrências
    var iter = re.iterator(texto);
    while (try iter.next()) |m| {
        std.debug.print("Match: {s}\n", .{m.slice});
    }
}
```

### Padrões Suportados

```zig
// Caracteres literais
try regex.Regex.compile(allocator, "abc");

// Classes de caracteres
try regex.Regex.compile(allocator, "[a-z]");       // range
try regex.Regex.compile(allocator, "[^0-9]");      // negação
try regex.Regex.compile(allocator, "\\d");          // dígito
try regex.Regex.compile(allocator, "\\w");          // word char
try regex.Regex.compile(allocator, "\\s");          // whitespace

// Quantificadores
try regex.Regex.compile(allocator, "a*");           // zero ou mais
try regex.Regex.compile(allocator, "a+");           // um ou mais
try regex.Regex.compile(allocator, "a?");           // zero ou um
try regex.Regex.compile(allocator, "a{3}");         // exatamente 3
try regex.Regex.compile(allocator, "a{2,5}");       // 2 a 5

// Âncoras
try regex.Regex.compile(allocator, "^inicio");      // início da string
try regex.Regex.compile(allocator, "fim$");          // fim da string

// Grupos
try regex.Regex.compile(allocator, "(ab)+");         // grupo de captura
try regex.Regex.compile(allocator, "(?:ab)+");       // grupo sem captura

// Alternação
try regex.Regex.compile(allocator, "gato|cachorro");
```

## PCRE2 via Interop C

Para regex completa com todas as funcionalidades PCRE2:

```zig
const c = @cImport({
    @cInclude("pcre2.h");
});

pub fn matchPcre(padrao: []const u8, texto: []const u8) !bool {
    var errorcode: c_int = undefined;
    var erroroffset: usize = undefined;

    const re = c.pcre2_compile_8(
        padrao.ptr,
        padrao.len,
        0,
        &errorcode,
        &erroroffset,
        null,
    ) orelse return error.CompilationFailed;
    defer c.pcre2_code_free_8(re);

    const match_data = c.pcre2_match_data_create_from_pattern_8(re, null)
        orelse return error.MatchDataFailed;
    defer c.pcre2_match_data_free_8(match_data);

    const rc = c.pcre2_match_8(
        re,
        texto.ptr,
        texto.len,
        0,
        0,
        match_data,
        null,
    );

    return rc >= 0;
}
```

## Regex Comptime

Uma das possibilidades mais interessantes do Zig é compilar expressões regulares em tempo de compilação:

```zig
fn comptimeRegex(comptime padrao: []const u8) type {
    return struct {
        // O padrão é analisado e otimizado em comptime
        const automato = comptime parsePattern(padrao);

        pub fn match(texto: []const u8) bool {
            var estado: usize = 0;
            for (texto) |char| {
                estado = automato.transicao(estado, char);
                if (estado == automato.estado_final) return true;
            }
            return false;
        }
    };
}

// Uso
const EmailMatcher = comptimeRegex("[a-zA-Z0-9]+@[a-zA-Z]+\\.[a-z]{2,4}");

test "regex comptime" {
    try std.testing.expect(EmailMatcher.match("user@exemplo.com"));
    try std.testing.expect(!EmailMatcher.match("invalido"));
}
```

## Parsers Combinadores

Para parsing mais complexo que regex, parsers combinadores são uma alternativa elegante:

```zig
const Parser = struct {
    pub fn literal(comptime expected: []const u8) fn ([]const u8) ?[]const u8 {
        return struct {
            fn parse(input: []const u8) ?[]const u8 {
                if (std.mem.startsWith(u8, input, expected)) {
                    return input[expected.len..];
                }
                return null;
            }
        }.parse;
    }

    pub fn digit(input: []const u8) ?struct { valor: u8, resto: []const u8 } {
        if (input.len > 0 and input[0] >= '0' and input[0] <= '9') {
            return .{ .valor = input[0] - '0', .resto = input[1..] };
        }
        return null;
    }

    pub fn manyDigits(input: []const u8) struct { valor: []const u8, resto: []const u8 } {
        var i: usize = 0;
        while (i < input.len and input[i] >= '0' and input[i] <= '9') : (i += 1) {}
        return .{ .valor = input[0..i], .resto = input[i..] };
    }
};
```

## Casos de Uso Comuns

### Validação de CPF

```zig
pub fn validarCpf(cpf: []const u8) bool {
    // Remover pontuação
    var digitos: [11]u8 = undefined;
    var pos: usize = 0;
    for (cpf) |c| {
        if (c >= '0' and c <= '9') {
            if (pos >= 11) return false;
            digitos[pos] = c - '0';
            pos += 1;
        }
    }
    if (pos != 11) return false;

    // Validar dígitos verificadores
    var soma: u32 = 0;
    for (0..9) |i| {
        soma += digitos[i] * @as(u32, @intCast(10 - i));
    }
    var resto = (soma * 10) % 11;
    if (resto == 10) resto = 0;
    if (resto != digitos[9]) return false;

    soma = 0;
    for (0..10) |i| {
        soma += digitos[i] * @as(u32, @intCast(11 - i));
    }
    resto = (soma * 10) % 11;
    if (resto == 10) resto = 0;
    return resto == digitos[10];
}
```

## Boas Práticas

1. **Prefira std.mem para buscas simples**: Mais rápido e sem dependências
2. **Use regex para padrões complexos**: Quando busca literal não é suficiente
3. **Compile regex uma vez**: Reutilize objetos compilados
4. **Considere comptime**: Para padrões conhecidos, compile em tempo de compilação
5. **Parsers combinadores para gramáticas**: Quando regex se torna ilegível

## Próximos Passos

Explore as [bibliotecas JSON](/ecossistema/zig-json-libs/) para parsing estruturado, as [bibliotecas CLI](/ecossistema/zig-cli-libs/) que usam pattern matching internamente, e os [frameworks de teste](/ecossistema/zig-testing-frameworks/) para testar seus padrões. Consulte nossos [tutoriais](/tutoriais/) para projetos práticos.
