Extrair seção intermediária de linhas de um arquivo de texto?


17

Estou escrevendo um script PHP para analisar um arquivo de texto grande para fazer inserções de banco de dados a partir dele. No entanto, no meu host, o arquivo é muito grande e atingi o limite de memória do PHP.

O arquivo tem cerca de 16.000 linhas; Quero dividi-lo em quatro arquivos separados (a princípio) para ver se consigo carregá-los.

A primeira parte que posso entender head -4000 file.txt. As seções do meio são um pouco mais complicadas - eu estava pensando em canalizar a tailsaída para head( tail -4001 file.txt | head -4000 > section2.txt), mas existe outra / melhor maneira?

Na verdade, minha lógica está confusa - para a seção dois, eu precisaria fazer algo assim tail -12001 file.txt | head - 4000e, em seguida, abaixar o tailargumento para as próximas seções. Eu já estou me confundindo! : P

Respostas:


27

Se você não quiser ficar confuso, mas ainda fazê-lo usando taile head, há uma maneira útil de invocar tailusando uma linha de contagem desde o início, não o fim:

tail -n +4001 yourfile | head -4000

... Mas uma ferramenta automática melhor feita apenas para dividir arquivos é chamada ... split! Também faz parte dos coreutils do GNU, portanto, qualquer sistema Linux normal deve tê-lo. Veja como você pode usá-lo:

split -l 4000 yourInputFile thePrefixForOutputFiles

(Veja man splitem caso de dúvida.)


19

Combinar cabeça e cauda como você funcionou, mas para isso eu usaria sed

sed -n '1,4000p' input_file # print lines 1-4000 of input_file

Isso permite que você resolva seu problema com uma função de shell rápida

chunk_it(){
    step=4
    start=1
    end=$step
    for n in {1..4} ; do
        sed -n "${start},${end}p" "$1" > "$1".$start-$end
        let start+=$step
        let end+=$step
    done
}

chunk_it your_file

Agora você tem o seu_arquivo.1-4000 e o seu_arquivo.4001-8000 e assim por diante.

Nota: requer bash


3
Eu gosto do jeito sed.
Fanchyna

Isso não funciona para mim porque o sed não sai. Ele imprime as linhas que eu quero stdout, mas eu tenho que pressionar Ctrl-c e, como resultado, não consigo redirecioná-lo para um arquivo. Alguma sugestão para torná-lo utilizável?
Brent212

Descobri isso! "sed -n '<linha_de_início>, <linha_de_end> w <arquivo de saída>' <ficheiro>" funciona para mim.
Brent212

@ Brent212 Outra opção a observar é que você também pode canalizá-lo para menos ou redirecionar a saída para um arquivo.
Kyle s
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.