Filtrando e dividindo um arquivo enorme baseado na coluna Windows

3

Eu tenho cerca de 2 TB de arquivos de dados formatados como

12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata

e eu quero retirar algumas datas. Por exemplo, talvez eu queira gerar os arquivos para 20/12/2015 e 22/12/2015.

12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata

e

12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata

Eu poderia facilmente fazer isso com o grep no linux fazendo grep '12/20/2015' filein > fileout20 e grep '12/22/2015' filein > fileout22 , mas isso tem dois problemas.

Primeiro, e mais importante, ele precisa passar pelo arquivo de entrada duas vezes para gerar a saída. Com 2 TB de dados e várias datas por arquivo, esse é um problema significativo. (Relacionado: Eu também não quero soluções que dividam o arquivo em todas as datas possíveis, porque eu não quero os dados da maioria das datas, apenas cerca de 10% de cada arquivo de entrada)

A segunda questão é que eu preciso rodar isso no Windows. (Eu sei que a maioria dos comandos Linux tem um equivalente no Windows usando o GnuWin32 ou algo parecido, então isso não é um problema tão grande)

Existe alguma maneira de fazer isso de maneira eficiente?

EDIT: As respostas até agora têm um dos dois problemas, então eu vou esclarecer um pouco. O primeiro problema é que não quero percorrer cada um dos arquivos de entrada mais de uma vez. Portanto, ter um loop para percorrer cada uma das datas não funcionará. Isso porque, se eu tiver 200 datas e 8000 arquivos, seriam necessárias 1.600.000 iterações.

O segundo problema é que eu quero dividir cada um dos arquivos de saída em um arquivo por data.

Portanto, com 200 datas e 8000 arquivos, deve haver 1.600.000 arquivos, mas com apenas 8.000 iterações do comando de pesquisa.

EDIT 2: aqui está uma solução com comandos do Linux. Eu provavelmente vou acabar usando isso a menos que alguém tenha uma maneira melhor

grep -f 12/20/2015 12/22/2015 filein1 > intermediate
awk -F, '{print > $1".out"}' intermediate

Este é um processo de dois estágios que primeiro filtra as datas e depois divide o resultado com base na data.

    
por Jay 23.12.2015 / 21:39

3 respostas

4

I don't want to run through each of the input files more than once.

To iterate through each of the dates will not work. I want to split each of the output files into one file per date.

Oh, por que você não acabou de dizer que não há iterações de um LOOP! ! . . .

Solução do PowerShell

(Defina suas variáveis de acordo com o exemplo abaixo: lista de strings, caminho do arquivo de saída e talvez nome da variável de string no formato MMDDAAAY)

Select-String -Path "C:\Path\*.txt" -Pattern 12/20/2015,12/23/2015,12/30/2015 -AllMatches | foreach-object {
   $RS = $_.Matches[0].Groups[0].Value.Replace("/","")
   $RS | Out-File "C:\Path\$RS.txt" -Append
}

(Acima está uma solução do PowerShell para pesquisar todo o conteúdo de arquivo de texto em um diretório específico em uma lista de cadeias. Ele também anexará todos os valores de sequência encontrados a um arquivo de saída com um nome de arquivo válido padrão, e isso é exclusivo para essa cadeia.)

Here is a solution in with Linux commands. I'll probably end up just using this

grep -f 12/20/2015 12/22/2015 filein1 > intermediate

awk -F, '{print > $1".out"}' intermediate

This is a two-stage process that first filters on the dates and then splits the result based on date.

Então você está pesquisando o conteúdo do arquivo de arquivos de texto em um determinado diretório com uma lista de seqüências de caracteres. Para cada string correspondente encontrada em cada arquivo, você precisa que seu valor seja escrito (e acrescentado, se aplicável) a um arquivo com um nome de arquivo "válido" que seja exclusivo da string - sem strings diferentes nos mesmos arquivos .

No que diz respeito a ser um modo "melhor" , é realmente uma questão de opinião, dependendo do que você está medindo estatística e recursos sábios, suponho. Eu não sabia que você estava super preocupado com uma ótima solução de desempenho em comparação com a maneira como você estava se inclinando para as obras.

(vou manter a solução de script em lote abaixo, caso alguém ache útil).

I want to pull out certain dates. For example, I might want to generate the files for 12/20/2015 and 12/22/2015.

Comment

However, unless I misunderstand findstr, there will only be one output file instead of one per date, which is not the behavior I am looking for.

Isso expandirá a outra solução para fornecer um nome de arquivo de string para anexar ao nome do arquivo original mais MMDDYYYY ou YYYYMMDD ou até mesmo qualquer combinação ou caracteres únicos do YYYY , MM ou DD partes da string correspondente para acrescentar ao nome do arquivo de THESE strings encontradas por arquivo - exatamente como você explicou.

Basicamente, você apenas define suas variáveis de acordo, salva como um script em lote [.cmd], e depois simplesmente o executa. A maioria das variáveis será explícita para o caminho completo específico dos diretórios aplicáveis.

Explicação da Variável de Script em Lote

  • O valor SET FilePath= será o caminho completo para o local onde os arquivos .TXT que você pesquisarão estão localizados

  • O valor SET StringList= será um local de caminho completo e um nome de arquivo em que você salvará um arquivo de texto com cada sequência (ou seja, 12/20/2015 , 12/22/2015 , etc.) para pesquisar no .txt arquivos. Você colocará uma string em cada linha do arquivo que será usada como string para encontrar nos arquivos .txt (veja o exemplo abaixo) .

  • Vou assumir que as outras variáveis e o resto da lógica do script em lote fazem sentido; caso contrário, deixe-me saber e ficarei feliz em adicionar mais marcadores para esclarecer, etc.

EXEMPLO DE SCRIPT DE LOTE

@ECHO ON

SET FilePath=C:\Path\<Location containing .TXT files to search>
SET StringList=C:\Path\DateList.txt

FOR %%A IN ("%FilePath%\*.txt") DO FOR /F "TOKENS=*" %%B IN (%StringList%) DO CALL :FindConCat "%%~B" "%%~NFXA" "%%~NA" "%%~XA"
GOTO EOF

:FindConCat
SET SearchStr=%~1
SET SearchFile=%~2
SET OutFName=%~3
SET FileExt=%~4
SET ParseStr=%SearchStr%
:::: --// MMDDYYY format
SET ParseStr=%ParseStr:~0,2%%ParseStr:~3,2%%ParseStr:~6,4%
:::: --// YYYYMMDD format
:: SET ParseStr=%ParseStr:~6,4%%ParseStr:~0,2%%ParseStr:~3,2%

FINDSTR /c:"%SearchStr%" "%SearchFile%">>"%FilePath%\%OutFName%_%ParseStr%%FileExt%"
GOTO EOF

EXEMPLO CONTEÚDO DO FILE DA LIST STRING ( SET StringList=C:\Path\DateList.txt )

12/15/2015
12/22/2015
12/23/2015
12/24/2015
    
por 24.12.2015 / 04:52
2

One-liner usando o PowerShell:

get-content c:\filein.txt | where-object { $_ -match "12/22/2015" } | out-file c:\fileout22.txt

    
por 23.12.2015 / 21:49
2
findstr -rc:"12/2[02]/2015" filein > fileout
    
por 23.12.2015 / 21:54