divide um arquivo por um prefixo de linha

2

Meus dados são assim:

60  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
61  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
62  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
63  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
64  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Eu quero dividi-lo em arquivos separados pelo prefixo da linha ... assim:

file 60 contains all lines prefixed with "60"
file 61 contains all lines prefixed with "61"
...

A melhor idéia que eu tive até agora foi procurar por todos os prefixos de linha, então percorrê-los e arrastar cada um deles para um arquivo separado, mas é um arquivo razoavelmente grande, então isso pode levar muito muito tempo. Talvez haja uma maneira melhor do que looping e grepping? Alguma maneira de agrupar o grep? Eu sei que há uma maneira de cortar o arquivo se houvesse marcadores entre cada seção como --- mas não tenho certeza se essa é a melhor maneira também.

    
por slf 15.07.2014 / 23:11

1 resposta

8

Se o arquivo de entrada é chamado data , uma solução é:

awk '{print>$1}' data

Em awk , o primeiro campo (coluna) é chamado $1 . Os loops acima através de cada linha de entrada ( awk faz isso implicitamente) e escreve essa linha em um arquivo cujo nome é o primeiro campo.

Mais detalhadamente:

  • O comando é colocado entre chaves. Como não há qualificador na frente das chaves, o comando será executado em todas as linhas de entrada.

  • O comando print , sem argumento, imprimirá toda a linha de entrada.

  • O símbolo > indica o redirecionamento da saída para um arquivo

  • O nome do arquivo é especificado como $1 , que, novamente, se refere ao texto que estava no primeiro campo da linha de entrada.

Assim, este comando criará arquivos chamados 60, 61 , etc., que conterão as linhas correspondentes do arquivo de entrada.

Manipulação de conjuntos de dados muito grandes

Por padrão, awk mantém todos os manipuladores de arquivos abertos até que todo o comando seja concluído. Consequentemente, com conjuntos de dados muito grandes, é possível exceder os limites do sistema no número de arquivos abertos. A solução mais simples é usar o append e fechar cada arquivo após a gravação:

awk '{print>>$1; close($1)}' data

Como isso usa >> (append), isso será adicionado aos arquivos de dados existentes, em vez de sobrescrevê-los. Se não for o que você deseja, exclua-os antes de executar este comando.

    
por 15.07.2014 / 23:16