Dividir um arquivo de texto em novos arquivos

0

Eu tenho um arquivo de texto no seguinte formato:

Model        1   
Atom….
Atom….
Atom….
ENDMDL
Model        2   
Atom….
Atom….
Atom….
ENDMDL
Model       n   
Atom….
Atom….
Atom….
ENDMDL

Eu preciso dividir este arquivo nos arquivos correspondentes a cada modelo. Os nomes dos novos arquivos de acordo com o número do modelo.

    
por Magdalena 14.06.2016 / 12:23

3 respostas

4

Isso é feito facilmente usando um pequeno script awk .

#!/usr/bin/awk -f 
# Write sections of the input file to separate files
# Written by PM 2Ring 2016.06.14

BEGIN{outbase = "outfile"}

/^Model/{outname = outbase $2}

{print > outname}

outbase é o nome do arquivo base. Ele recebe o número do modelo anexado a ele, portanto, para o arquivo de amostra, os arquivos de saída outfile1 , outfile2 , etc serão criados. Com uma pequena alteração no script, você pode definir outbase na linha de comando, usando a opção -v do awk.

O coração deste script é

/^Model/{outname = outbase $2}

Ele diz: Se a linha atual começar com "Modelo", anexe o conteúdo do campo # 2 à sequência outbase , atribuindo o resultado a outname .

Por padrão, o awk processa um arquivo linha por linha, dividindo cada linha em campos usando espaço em branco como o separador de campo.

{print > outname}

simplesmente imprime a linha atual no arquivo cujo nome está armazenado em outname .

Este script é pequeno o suficiente para escrever tudo na linha de comando:

awk 'BEGIN{outbase = "outfile"}; /^Model/{outname = outbase $2}; {print > outname}' infile.txt

Você pode realmente fornecer vários argumentos de arquivo de entrada e eles serão tratados corretamente, contanto que você não tenha números de modelo duplicados.

    
por 14.06.2016 / 13:17
1

Eu provavelmente usaria csplit para isso. Isso funcionará para um arquivo chamado file.txt :

csplit -ksz file.txt '/^Model/' '{*}'
for xx in xx*
do
    newname=$(awk '{print $2; exit}' "$xx")
    test ! -f "$newname" && mv -f "$xx" "$newname"
done

O csplit divide file.txt em várias partes com base no RE. Os nomes de arquivos são (por padrão) denominados xx e um sufixo numérico crescente e monotônico. Analisamos cada um deles e os renomeamos para o número do modelo encontrado dentro do arquivo.

Todos os arquivos correspondentes a xx* no final do loop contêm números de modelo duplicados (a renomeação é realizada em uma base primeiro a chegar, primeiro a ser veiculada ).

    
por 14.06.2016 / 13:55
0
#!/bin/bash                                                                                                                                                                                                                                   

while read -r line                                                                                                                                                                                                                            
do                                                                                                                                                                                                                                            
    case $line in                                                                                                                                                                                                                             
        Model*)                                                                                                                                                                                                                               
            f="${line//[[:space:]]/}"
            touch "$f"  # file name without white spces                                                                                                                                                                                                                     
            ;;                                                                                                                                                                                                                                
        ENDMDL)                                                                                                                                                                                                                               
            :                                                                                                                                                                                                                                 
            ;;                                                                                                                                                                                                                                
        *)                                                                                                                                                                                                                                    
            echo "$line" >> "$f"                                                                                                                                                                                                              
            ;;                                                                                                                                                                                                                                
    esac                                                                                                                                                                                                                                      
done < "$1"

Algo parecido com isto. Você deve executá-lo fornecendo o arquivo de modelos como argumento: ./script_name models.txt

Note que, como mencionado por @PM 2Ring, esta abordagem é lenta, especialmente se você tiver arquivos grandes.

    
por 14.06.2016 / 12:51