Procura por muitas cadeias diferentes em muitos arquivos de log diferentes?

0

Eu tenho uma lista de arquivos que desapareceram em algum lugar em nosso sistema no trabalho. Eu também tenho uma pasta cheia de 41 arquivos de log adicionando até 46 MB que esperamos ter entradas de log relativas aos arquivos ausentes. Como eu poderia grep esses arquivos de log para qualquer valor na minha lista?

A lista é estruturada como um arquivo por linha sem extensão de arquivo. Os logs parecem ter uma estrutura, mas ainda não estou totalmente familiarizado com essa estrutura. Ele contém nomes de arquivos e caminhos, bem como o que foi feito para isso.

Eu sei que posso cat * todos os arquivos de log e canalizá-lo para grep . Provavelmente usarei -A e -B para obter um pouco de contexto dos arquivos de log quando um nome for encontrado. Eu estou usando o GnuWin32 no Windows para poder juntar isso com o Powershell, mas acho que isso exigiria que um nome de arquivo mostrasse todos os 46 MB e, quando eu passasse para o próximo nome de arquivo, eu recomeçasse. Eu tenho 1830 arquivos na lista, então, se eu tiver que começar de novo com cada um, acabarei lendo 46 MB tantas vezes que lidarei com GBs de dados repetidos. Parece ineficiente fazer isso dessa maneira.

Suponho que eu poderia criar um regex grande dos arquivos de 1830 ou juntos e executá-lo uma vez nos logs, mas isso é viável? O regex seria quase 30KB (1830 arquivos * comprimento médio do nome do arquivo de cerca de 16 caracteres = 29280 bytes para não mencionar outros 1830 bytes de símbolos pipe).

Editar: Aqui está o que estou fazendo agora quando estou na pasta de registros e a lista está em uma pasta:

$logs = gc *
$notfound = gc ../notfound.txt
$logs | % { $i = 0; while ($i -lt $notfound.Count) { if ($_ -contains $notfound[$i]) { echo $_ }; $i++; } } | out-file C:\discovered.txt

É totalmente powershell. Eu estou pronto para usar qualquer ferramenta para acelerar isso, porque agora há 550991 linhas em todos os arquivos de log combinados e há 1830 nomes de arquivos, então essa abordagem está fazendo 1.008.313.530 comparações . Está tudo na memória, então pelo menos eu não tenho disco de E / S me atrasando. Eu poderia ser capaz de sair do while se o if se tornar verdade, mas ainda vou fazer tantas comparações, não tenho certeza se otimizar isso realmente fará algum bem. Já está funcionando há meia hora. Eu estou bem em reescrever minha abordagem da linha 1 se eu puder fazê-lo antes de ir para casa no final de semana.

    
por Corey Ogburn 17.01.2014 / 18:13

1 resposta

0

Seria mais eficiente extrair os nomes dos arquivos por meio de uma expressão regular e ver se cada um deles está em sua lista. Poderia ser algo assim:

$notfound = gc ../notfound.txt
gc * |
        select-string -AllMatches '\(?<filename>[^\]+)\.txt' | 
        select -ExpandProperty Matches |
        % { $_.Groups['filename'].Value } |
        ? { $notfound -contains $_ } |
        out-file C:\discovered.txt

Eu estou procurando por arquivos que se parecem com "\ something.txt". Você terá que mudar isso.

Se ainda for muito lento e sua lista não encontrada for muito grande, talvez seja mais eficiente carregá-lo em um .Net HashSet, mas eu não faria isso a menos que necessário.

    
por 20.01.2014 / 03:25