reorganização do arquivo de dados

1

Eu tenho um arquivo .data e preciso reorganizá-lo para que três linhas consecutivas sejam unidas em uma única linha. Só para ficar claro, eu tenho o seguinte ...

D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,
C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,
A = 0.007425, ALP = 1.000000, EPS = 1.000000,
FX = -0.355305, FY = 0.857782, FZ = 0.282590;

... e assim por diante

e eu preciso de tudo isso em uma única linha:

D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 ...

e eu preciso disso em todo o documento. Existe uma maneira rápida de fazer isso?

A outra dificuldade é que todas as informações a serem unidas estão às vezes em 3 linhas diferentes e às vezes em 2 ou 4 linhas diferentes. A única coisa que tenho é que cada linha é identificada por um D .... É possível fazê-lo? Como?

Basicamente, cada nova linha deve começar com D611102, que é o número do nó. E eu preciso de uma única linha grande com T = ..., C = ..., até FZ = ...., etc. Cada linha completa deve ter todos os dados até o;

Para ser mais claro, tenho o seguinte: ...

   D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,
     C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,
     A = 0.007425, ALP = 1.000000, EPS = 1.000000,
     FX = -0.355305, FY = 0.857782, FZ = 0.282590;
    D611103 = 'SVM_PRS_Hydr_L01', T = 0.0,
     C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,
     A = 0.007425, ALP = 1.000000, EPS = 1.000000,
     FX = -0.656518, FY = 0.656518, FZ = 0.282590;

... etc ... E eu preciso disso:

D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,A = 0.007425, ALP = 1.000000, EPS = 1.000000,FX = -0.355305, FY = 0.857782, FZ = 0.282590; (all in a single line)
D611103 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,A = 0.007425, ALP = 1.000000, EPS = 1.000000,FX = -0.656518, FY = 0.656518, FZ = 0.282590; 

(tudo em uma única linha) e assim por diante, para todo o documento.

    
por sarde88 09.12.2015 / 10:57

2 respostas

2

Se bem entendi, basicamente você quer remover todas as quebras de linha que não ocorrem diretamente após um ; . Se sim, você pode fazer:

perl -pe 's/(?<!;)\s*\n/ /' file > newfile

Ou, para editar o arquivo, use -i :

perl -i.bak -pe 's/(?<!;)\s*\n/ /' file

O texto acima fará as alterações em file e criará um backup do original chamado file.bak . Para pular a criação do backup, use apenas -i sem uma extensão.

Explicação

O -p significa "imprimir todas as linhas de entrada depois de aplicar o script fornecido por -e . O s/// é o operador de substituição. Seu formato geral é s/pattern/replacement/ e substituirá pattern por replacement .

Nesse caso, pattern é 0 ou mais caracteres de espaço em branco ( \s* ) seguidos por uma nova linha ( \n ) que não são precedidos por ; . A construção (?<!foo)bar é um lookbehind negativo , corresponderá a bar se os caracteres anteriores não forem foo . Portanto, o script acima removerá todas as novas linhas que não sejam depois de um ; .

    
por terdon 09.12.2015 / 11:11
1

O script abaixo deve fazer o trabalho. Como ele lê por linha, ele deve ser relativamente rápido em arquivos maiores, mas não foi testado em um arquivo grande.

#!/usr/bin/env python3
import sys

f = sys.argv[1]

s = ""

with open(f) as lines:
    for l in  lines:
        if l.startswith("D"):
            print(s+l.strip(), end = "")
            s = "\n"
        else:
            print(l.strip(), end = "")

Use

  • Copie-o em um arquivo vazio, salve-o como combine_lines.py
  • Execute-o pelo comando:

    python3 /path/to/combine_lines.py <.data_file>
    

Explicação

O script lê as linhas, linha por linha. Se a linha começa com um D , senão a linha é simplesmente impressa após a linha existente, exceto para a primeira linha.

Teste:

D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,
A = 0.007425, ALP = 1.000000, EPS = 1.000000,
FX = -0.355305, FY = 0.857782, FZ = 0.282590;
D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,
A = 0.007425, ALP = 1.000000, EPS = 1.000000,
FX = -0.355305, FY = 0.857782, FZ = 0.282590;

torna-se:

D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,A = 0.007425, ALP = 1.000000, EPS = 1.000000,FX = -0.355305, FY = 0.857782, FZ = 0.282590;
D611102 = 'SVM_PRS_Hydr_L01', T = 0.0,C = 3.341441E-006 * Cp_SVM_PRS_Pi001 * Dens_SVM_PRS_Pi001,A = 0.007425, ALP = 1.000000, EPS = 1.000000,FX = -0.355305, FY = 0.857782, FZ = 0.282590;

EDITAR

ou

como sugerido por @terdon, usando o final ";" como um acionador, o que nos dá a oportunidade de ignorar o truque s = :

#!/usr/bin/env python3
import sys

f = sys.argv[1]

with open(f) as lines:
    for l in  lines:
        l = l if l.endswith(";\n") else l.strip(); print(l, end = "")

Comparando o Perl ao python

Em um arquivo relativamente grande, 550MB, 9006121 linhas:

Perl:

$ time perl -pe 's/(?<!;)\s*\n/ /' '/home/jacob/Bureaublad/data_large' > '/home/jacob/Bureaublad/data_large2'

real    0m27.171s
user    0m25.536s
sys     0m1.054s

Python:

time '/home/jacob/Bureaublad/pscript_9.py' '/home/jacob/Bureaublad/data_large' > '/home/jacob/Bureaublad/data_large2'

real    0m15.235s
user    0m13.806s
sys     0m1.279s

Em um arquivo menor, 51 KB, 838 linhas:

$ time perl -pe 's/(?<!;)\s*\n/ /' '/home/jacob/Bureaublad/data_small' > '/home/jacob/Bureaublad/data_small2' 

real    0m0.008s
user    0m0.007s
sys     0m0.000s

Python:

$ time '/home/jacob/Bureaublad/pscript_9.py' '/home/jacob/Bureaublad/data_small' > '/home/jacob/Bureaublad/data_small2' 

real    0m0.033s
user    0m0.019s
sys     0m0.011s

O resultado é que, se você tiver arquivos maiores, python pode ser o que você gostaria de usar, se você tiver muitos arquivos menores, Perl é a melhor opção.

    
por Jacob Vlijm 09.12.2015 / 11:41