🌗 ← Índice

🐍 Python P09 — Strings, Formatação e Regex


Data: 09/07/2026

Nível: Intermediário




String é o tipo de dado que mais aparece em código real — logs, nomes de arquivo, respostas de API, saída pro usuário. Hoje tu vai dominar manipulação de texto e aprender regex: o canivete suíço dos padrões.




🎯 O que vamos aprender


  • Formatação avançada: f-strings, `format()`, alinhamento
  • Métodos essenciais: `split()`, `join()`, `strip()`, `replace()`
  • Busca e verificação: `in`, `startswith()`, `find()`
  • Regex com `re`: padrões, grupos, substituição
  • Caso real: parser de log



  • 📝 Formatação com f-strings (Python 3.6+)


    
    nome = "Hugo"
    idade = 30
    print(f"Olá, {nome}! Você tem {idade} anos.")
    
    # Alinhamento e largura
    print(f"|{'Esquerda':<15}|{'Centro':^15}|{'Direita':>15}|")
    # |Esquerda       |    Centro     |         Direita|
    
    # Números
    pi = 3.14159265
    print(f"PI = {pi:.2f}")          # PI = 3.14
    print(f"R${12345.6:,.2f}")       # R$12,345.60
    
    # Datas
    from datetime import datetime
    hoje = datetime.now()
    print(f"{hoje:%d/%m/%Y %H:%M}")  # 09/07/2026 08:00
    



    🔧 Métodos essenciais de string


    
    texto = "  Hugo Costa da Silva  "
    
    # Limpeza
    print(texto.strip())       # "Hugo Costa da Silva" (remove bordas)
    print(texto.lower())       # "  hugo costa da silva  "
    print(texto.upper())       # "  HUGO COSTA DA SILVA  "
    print(texto.title())       # "  Hugo Costa Da Silva  "
    
    # Busca e substituição
    print("Hugo" in texto)            # True
    print(texto.find("Costa"))        # 7 (índice onde começa)
    print(texto.replace("Hugo", "HB")) # "  HB Costa da Silva  "
    print(texto.startswith("  Hugo"))  # True
    
    # Divisão e junção (as mais usadas!)
    partes = texto.strip().split(" ")  # ["Hugo", "Costa", "da", "Silva"]
    junto = "-".join(partes)           # "Hugo-Costa-da-Silva"
    
    # Verificação de tipo
    "123".isdigit()      # True
    "abc123".isalnum()   # True
    "Hugo".isalpha()     # True
    



    🎯 `split()` e `join()` — o par dinâmico


    
    # CSV caseiro
    linha = "Hugo,30,Brasília,Python"
    dados = linha.split(",")  # ["Hugo", "30", "Brasília", "Python"]
    
    # Reconstrói com outro separador
    pipe = "|".join(dados)    # "Hugo|30|Brasília|Python"
    
    # Log real
    log = '2026-07-09 08:30:15 ERRO: conexão recusada'
    partes = log.split(" ", 3)  # Divide em no máximo 4 partes
    # ['2026-07-09', '08:30:15', 'ERRO:', 'conexão recusada']
    



    🔍 Regex com `re` — vai além do `in`


    Regex (Regular Expression) é uma mini-linguagem pra buscar padrões em texto.


    
    import re
    
    texto = "Contato: hugo@email.com ou hugo.costa@hbstudio.com.br"
    
    # Encontrar todos os emails
    emails = re.findall(r'[\w.]+@[\w.]+\.\w+', texto)
    print(emails)  # ['hugo@email.com', 'hugo.costa@hbstudio.com.br']
    
    # Verificar se existe
    if re.search(r'email', texto):
        print("Tem 'email' no texto")
    
    # Substituir padrão
    anonimizado = re.sub(r'[\w.]+@[\w.]+\.\w+', '[EMAIL]', texto)
    print(anonimizado)  # Contato: [EMAIL] ou [EMAIL]
    

    Grupos de captura


    
    log = "2026-07-09 08:30:15 ERRO: conexão recusada no host 192.168.1.1"
    
    match = re.search(
        r'(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+(\w+):\s+(.+)',
        log
    )
    
    if match:
        print(f"Data: {match.group(1)}")   # 2026-07-09
        print(f"Hora: {match.group(2)}")   # 08:30:15
        print(f"Nível: {match.group(3)}")  # ERRO
        print(f"Mensagem: {match.group(4)}") # conexão recusada...
    



    🧩 Tabela rápida de padrões regex


    PadrãoSignificadoExemplo

    |---|---|---|

    `\d`Dígito (0-9)`\d{3}` → "123"
    `\w`Letra, número ou `_``\w+` → "hugo_costa"
    `\s`Espaço, tab, newline`\s+` → qualquer espaço
    `.`Qualquer caractere`h.g` → "hug", "hag"
    `+`1 ou mais`\d+` → "12345"
    `*`0 ou mais`\d*` → "" ou "123"
    `?`0 ou 1`a?` → "" ou "a"
    `{n,m}`Entre n e m vezes`\d{2,4}` → "12", "1234"
    `[abc]`a, b ou c`[Hh]ugo` → "Hugo" ou "hugo"
    `^`Início da string`^Olá` → começa com Olá
    `$`Fim da string`fim$` → termina com fim
    `()`Grupo de captura`(Hugo)\s(Costa)`



    💡 Caso real: parser de log


    
    import re
    
    log = """
    2026-07-09 08:30:15 INFO: servidor iniciado na porta 8080
    2026-07-09 08:31:02 ERRO: conexão recusada (timeout 5s)
    2026-07-09 08:32:45 WARN: disco com 90% de uso
    2026-07-09 08:35:00 INFO: 150 requisições processadas
    """
    
    # Extrai nível e mensagem de cada linha
    padrao = r'(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+(\w+):\s+(.+)'
    registros = re.findall(padrao, log)
    
    erros = [r for r in registros if r[2] == "ERRO"]
    print(f"Total de erros: {len(erros)}")
    for data, hora, nivel, msg in erros:
        print(f"  [{data} {hora}] {msg}")
    



    ✍️ Exercícios


    1. Validador de CPF simples

    Crie validar_cpf(cpf) que verifica se a string tem 11 dígitos (ignore . e -). Use regex e re.sub.


    
    import re
    # Teu código aqui
    

    2. Extrator de URLs

    Dado um texto, extraia todas as URLs (http://... ou https://...) com re.findall.


    
    texto = "Visite https://www.python.org e também http://example.com/path"
    # Teu código aqui — deve retornar lista com as 2 URLs
    

    3. Normalizador de nomes

    Crie normalizar(nome) que:

  • Remove espaços extras (`.strip()`)
  • Converte pra title case
  • Remove acentos (pode usar replace manual)

  • 
    # Teu código aqui
    



    🧪 Desafio


    Crie um analisador de arquivo de log que:

    1. Lê um arquivo servidor.log (crie um de exemplo)

    2. Extrai data, hora, nível e mensagem de cada linha com regex

    3. Agrupa por nível (INFO, ERRO, WARN)

    4. Exibe um resumo: total de linhas, quantos erros, avisos

    5. Lista só os ERROS com data/hora


    
    # Teu código aqui
    



    ✅ Gabarito


    Exercício 1 — Validador de CPF


    
    import re
    
    def validar_cpf(cpf):
        # Remove tudo que não for dígito
        digitos = re.sub(r'\D', '', cpf)
        return len(digitos) == 11
    
    print(validar_cpf("123.456.789-00"))  # True
    print(validar_cpf("123.456"))          # False
    


    Exercício 2 — Extrator de URLs


    
    import re
    
    def extrair_urls(texto):
        return re.findall(r'https?://[^\s]+', texto)
    
    texto = "Visite https://www.python.org e também http://example.com/path"
    print(extrair_urls(texto))
    # ['https://www.python.org', 'http://example.com/path']
    


    Exercício 3 — Normalizador de nomes


    
    def normalizar(nome):
        nome = nome.strip().title()
        # Remove acentos (simplificado)
        mapa = {'Á':'A', 'À':'A', 'Ã':'A', 'Â':'A', 'É':'E', 'Ê':'E',
                'Í':'I', 'Ó':'O', 'Ô':'O', 'Õ':'O', 'Ú':'U', 'Ç':'C'}
        for acento, sem in mapa.items():
            nome = nome.replace(acento, sem)
        return nome
    
    print(normalizar("  hugo côsta da sálva  "))
    # "Hugo Costa Da Salva"
    


    Desafio — Analisador de logs


    
    import re
    
    # Criar log de exemplo
    with open("servidor.log", "w") as f:
        f.write("""2026-07-09 08:30:15 INFO: servidor iniciado
    2026-07-09 08:31:02 ERRO: conexao recusada
    2026-07-09 08:32:45 WARN: disco 90%
    2026-07-09 08:35:00 INFO: 150 reqs
    2026-07-09 08:40:11 ERRO: timeout API
    """)
    
    # Analisar
    padrao = r'(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+(\w+):\s+(.+)'
    
    with open("servidor.log") as f:
        linhas = f.readlines()
    
    registros = []
    for linha in linhas:
        match = re.search(padrao, linha)
        if match:
            registros.append(match.groups())
    
    # Resumo
    total = len(registros)
    erros = [r for r in registros if r[2] == "ERRO"]
    warns = [r for r in registros if r[2] == "WARN"]
    infos = [r for r in registros if r[2] == "INFO"]
    
    print(f"Total de linhas: {total}")
    print(f"ERRO: {len(erros)} | WARN: {len(warns)} | INFO: {len(infos)}")
    print("\n--- ERROS ---")
    for data, hora, _, msg in erros:
        print(f"  [{data} {hora}] {msg}")
    




    **Próxima aula:** P10 — Desafio Final Mês 1 (projeto integrador!)