Extrair apenas certas linhas de um arquivo texto. (Python/Powershell)

Extrair apenas certas linhas de um arquivo texto. (Python/Powershell)

Overview

Se você já se viu perdido enquanto procurava por uma agulha no palheiro em um arquivo de log gigantesco, esse post é a luz no fim do túnel! Vou guiar você pelo processo de extração de linhas específicas utilizando Python e PowerShell, duas ferramentas poderosas para analisar e filtrar dados. Com exemplos práticos e direto ao ponto, espero que essa leitura transforme sua maneira de lidar com arquivos texto. Preparado para tornar sua vida infinitamente mais fácil? Vamos nessa!

A ideia deste post é demonstrar uma das formas de se extrair de um arquivo texto, apenas linhas que possuam determinada palavra-chave. Este tipo de abordagem é especialmente útil quando precisamos procurar um texto em um log muito grande. Vou mostrar como fazer isso em Python e o equivalente utilizando PowerShell.

Obvio que as soluções que vou apresentar não são soluções finais ou únicas, mas podem ajudar que estiver passando por este tipo de situação: Analisar toneladas de texto e tentar descobrir onde deu ruim.

Primeiro vamos definir alguns pontos em comum nas duas abordagens (Python e Powershell):

  1. Nome do arquivo que vai ser lido. (in_file = “big_logfile.txt”)
  2. O arquivo que vai receber as linhas extraídas. (out_file = “file_with_extractedlines.txt”)
  3. Qual texto queremos encontrar nas linhas do arquivo (search_for = “ERROR”)
  4. O número da linha que está sendo lida (line_num = 0)
  5. Quantidade de linhas encontradas (lines_found = 0)

Uma observação importante: Não vou adicionar rotinas de verificação se o texto está maiúsculo ou minusculo, mas você deve ter isso em mente.

Utilizando Python!

Primeiro, vamos declaras as variáveis que vamos precisar:

in_file = "big_logfile.txt"
out_file = "file_with_extractedlines.txt"

search_for = "ERROR"
line_num = 0
lines_found = 0

As três primeiras variáveis são as que estabelecemos no inicio deste post. As duas últimas (line_num e lines_found) são, respectivamente o número da linha que está sendo lida e a quantidade de linhas que possuem o texto procurado (search_for).

O próximo passo é abrir o arquivo de saída, o arquivo de log e fazer a interação pelas linhas.

with open(out_file, 'w') as out_f:
    with open(in_file, "r") as in_f:
        for line in in_f:
            line_num += 1
            if search_for in line:
                lines_found += 1
                print("Found '{}' in line {}...".format(search_for, line_num))
                out_f.write(line)

        print("Found {} lines...".format(lines_found))

Explicando (linha a linha) o que este script faz:

  1. Primeiro abrimos o arquivo de saída (referenciado na variável out_f), que vai armazenas as linhas que contém o texto que procuramos;
  2. Depois abrimos o arquivo de LOG (referenciado na variável in_f);
  3. A terceira linha é a declaração da iteração que faremos com o arquivo de log (in_f) para verificar linha a linha;
  4. Na quarta linha, incremento o valor de line_num, que guarda o número da linha que estamos lendo. Poderia utilizar o enumerate, mas imagino que isso poderia gerar perda de performance;
  5. Depois verificamos se o texto que queremos (search_for) existe na linha que estamos lendo (line). As linhas 6, 7 e 8 ocorrem apenas se o texto for encontrado na linha:
  6. Incremento o número de linhas que possuem o texto (lines_found);
  7. Mostro uma mensagem no console, falando que encontrei uma linha com o texto e qual o número dela (no arquivo original);
  8. Escrevo no arquivo de saída (out_f);
  9. No final de tudo, mostro uma mensagem falando a quantidade de linhas que encontrei.

Utilizando Powershell!

A abordagem que vamos utilizar no PowerShell é (basicamente) a mesma.

Primeiro, vamos declarar as variáveis que vamos utilizar:

$in_file = "big_logfile.txt"
$out_file = "file_with_extractedlines.txt"
$search_for = "ERROR"
$line_num = 0
$lines_found = 0

As variáveis são as mesmas e com os mesmos propósitos:

  • $in_file: Arquivo contendo as linhas que serão examinadas;
  • $out_file: Arquivo que receberá as linhas extraídas;
  • $search_for: Texto que será procurado em cada linha;
  • $line_num: Número da linha que está sendo examinada;
  • $lines_found: Quantidade de linhas encontradas;

A “grande” diferença entre a abordagem com Python e a com o Powershell é a seguinte:

$log_lines = Get-Content $in_file # Var holding the lines of the log file.

O comando acima recupera o conteúdo do arquivo de log e o armazena na variável log_lines.

Agora, vamos para o processamento das linhas:

foreach ($line in $log_lines) { 
    $line_num++    
    if ($line.Contains($search_for)) {
        $lines_found++
        Write-Host "Text '$search_for' found in line $line_num..."
        $line | out-file -FilePath $out_file -Append
    }
}

Write-Host "Found $lines_found lines..."

Explicando (linha a linha) o que este script faz:

  1. Uma vez que já possuímos o conteúdo do arquivo, a primeira linha inicia uma iteração por cada linha do arquivo;
  2. Na segunda linha incrementamos o número da linha que está sendo lida;
  3. Depois verificamos se o texto que queremos (search_for) existe na linha que estamos lendo (line). As linhas 6, 7 e 8 ocorrem apenas se o texto for encontrado na linha:
  4. Incremento o número de linhas que possuem o texto (lines_found);
  5. Mostro uma mensagem no console, falando que encontrei uma linha com o texto e qual o número dela (no arquivo original);
  6. Escrevo no arquivo de saída (out_file);
  7. No final de tudo, mostro uma mensagem falando a quantidade de linhas que encontrei.

Observações sobre ambas abordagens

  1. A parte de contar as linhas encontradas, os prints e mostrar qual linha estamos lendo (obviamente) são opcionais e você pode remove-las sem problemas.
  2. Exemplo em Python (Github): https://github.com/brenordv/python-snippets/blob/master/extract-lines/extract_lines.py
  3. Exemplo em PowerShell (Github): https://github.com/brenordv/powershell-snippets/blob/master/extract-line/extract_lines.ps1

Espero ter ajudado.