Ajuda para ler um arquivo simples no unix e exportar para formato csv simplificado para importar para o excel

0

Eu tenho um arquivo de texto que possui dados gravados no formato abaixo, seus milhares de linhas.

  1. O novo registro sempre começa com WHATEVER.RDNDISPLAY ou WHATEVER.DSPLY_NAME.
  2. O nome do registro é QUALQUER
  3. A linha termina com "seguida de branco, significa que nenhum dado ou algum texto data ou string ou número +100 ou -100
  4. ignorar os espaços abaixo porque não há, isso é só vi que eu posso exibi-lo corretamente nesse site. então o arquivo simples tem milhares de linhas em cada registro.

Esquema

  Field separator
       v           v quote followed by blank or data  (numbers or text or even + or -)
TEST_AP.RDNDISPLAY "
   ^       ^ Field Name
Record name

Exemplo

---------------
TEST_AB.RDNDISPLAY "
TEST_AB.DSPLY_NAME "
TEST_AB.TIMACT "
TEST_AB.NETCHNG_1 "
TEST_AB.TRADE_DATE "
TEST_AB.ACTIV_DATE "
TEST_AB.BID "
TEST_AB.ASK "
TEST_AB.MATUR_DATE "
TEST_AB.COUPN_RATE "
TEST_AB.MID_PRICE "
TEST_AB.MKT_MKR_NM "
TEST_AB.RECORDTYPE "
TEST_AB.SETTLEDATE "
TEST_AB.BID_YIELD "
TEST_AB.ASK_YIELD "
TEST_AB.GEN_VAL1 "
TEST_AB.GEN_VAL2 "
TEST_AB.GEN_VAL3 "
TEST_AB.GEN_VAL4 "
TEST_AB.SPARE_NM1 "
TEST_AB.SPARE_NM2 "
TEST_AB.SPARE_NM3 "
TESTRICU=L.DSPLY_NAME "TEST
TESTRICU=L.TIMACT "
TESTRICU=L.TRDPRC_1 "
TESTRICU=L.CURRENCY "GBP
TESTRICU=L.TRADE_DATE "
TESTRICU=L.TRDTIM_1 "
TESTRICU=L.OPEN_PRC "
TESTRICU=L.HST_CLOSE "
TESTRICU=L.BID "
TESTRICU=L.ASK "0
TESTRICU=L.BIDSIZE "
TESTRICU=L.ASKSIZE "
TESTRICU=L.YIELD "
TESTRICU=L.PERATIO "
TESTRICU=L.PCTCHNG "
TESTRICU=L.CLOSE_BID "
TESTRICU=L.CLOSE_ASK "
TESTRICU=L.STRIKE_PRC "
TESTRICU=L.MATUR_DATE "31 Dec 1906
TESTRICU=L.COUPN_RATE "+4
TESTRICU=L.OFFCL_CODE "1003
TESTRICU=L.HSTCLSDATE "
TESTRICU=L.BOND_TYPE "
TESTRICU=L.BCKGRNDPAG "
TESTRICU=L.ISSUE_DATE "01 Jan 2004
TESTRICU=L.PUTCALLIND "
TESTRICU=L.NAVALUE "
TESTRICU=L.NAV_NETCHN "
TESTRICU=L.MID_PRICE "
TESTRICU=L.EUROCLR_NO "
TESTRICU=L.CEDEL_NO "
TESTRICU=L.VALOREN_NO "100
TESTRICU=L.NAVDATE "
TESTRICU=L.NAVALUE_1 "
TESTRICU=L.NAVDAT_1 "
TESTRICU=L.PRTY_PRICE "
TESTRICU=L.ISSUE_PRC "

Eu quero ser capaz de extrair este arquivo em formato de tabela que pode ser lido em excel no formato de coluna com valores de dados preenchendo em linhas. Então, colocar seria parecido com

RECORDNAME       RDNDISPLAY  DSPLY_NAME CURRENCY TIMACT NETCHNG_1 TRADE_DATE ACTIV_DATE BID ASK MATUR_DATE COUPN_RATE OFFCL_CODE ISSUE_DATE VALOREN_NO  .... so on
TEST_AB          ;
TESTRICU=L       ;          ;TEST      ;  GBP    ;       ;             ;             ;  ;   0   31 Dec 1906 ;  +4      ; 1003    ;  01 Jan 2004 ; 100     .... so on

Então, talvez o código procure por todos os nomes de campos possíveis e leia o arquivo novamente. Pesquise RDNDISPLAY ou DSPLY_NAME para saber o início e o fim do registro (início de outro registro) extraia o nome do registro, por exemplo, WHATEVER e coloque na linha formato sob cada cabeçalho de campo. faça isso para cada registro, se o nome bruto não existir em um arquivo for substituído por; para que, uma vez importado para o excel, seja fácil de fazer.

    
por Sal Allan 06.02.2015 / 18:36

2 respostas

2

Há algumas coisas complicadas com o CSV: um campo contém um separador de campo incorporado ou um campo contém cotações incorporadas. Eu adicionei 2 linhas aos seus dados de amostra:

TEST_AB.foo " with "embedded quotes" here
TESTRICU=L.foo " with an inner; semicolon

E uma solução assustadora de perl é: salve isso em um arquivo chamado "text2csv.sh"

#!/bin/sh
perl -lne '
      @F = split /\s*"\s*/, $_, 2;
      ($record, $field) = split /\./, $F[0];
      $fields{$field} = 1;
      $records{$record} = 1;
      $data{$record}{$field} = $F[1];
  } END {
      print join ";", "RECORDNAME", keys %fields;
      for my $rec (keys %records) {
          print join";", $rec, map {
                                   $q=0;
                                   if (/"/) {s/\"/\"\"/g; $q=1}
                                   if (/;/) {$q=1}
                                   $q ? qq{"$_"} : $_
                               } @{$data{$rec}}{keys %fields};
      }
' "$1" > "$1.csv"

E corra assim:

sh text2csv.sh /path/to/myfile.txt
cat /path/to/myfile.txt.csv
RECORDNAME;PERATIO;NAVALUE_1;ISSUE_PRC;BCKGRNDPAG;GEN_VAL2;SPARE_NM2;GEN_VAL3;COUPN_RATE;DSPLY_NAME;CLOSE_BID;NAVALUE;VALOREN_NO;TRDTIM_1;PRTY_PRICE;ISSUE_DATE;RECORDTYPE;OFFCL_CODE;MID_PRICE;BID;TRDPRC_1;ASK;ACTIV_DATE;STRIKE_PRC;HSTCLSDATE;ASK_YIELD;MATUR_DATE;NAV_NETCHN;NAVDATE;PCTCHNG;TRADE_DATE;BIDSIZE;NAVDAT_1;ASKSIZE;MKT_MKR_NM;foo;OPEN_PRC;NETCHNG_1;BID_YIELD;RDNDISPLAY;YIELD;CURRENCY;TIMACT;GEN_VAL1;HST_CLOSE;PUTCALLIND;CLOSE_ASK;SPARE_NM3;BOND_TYPE;SPARE_NM1;SETTLEDATE;EUROCLR_NO;GEN_VAL4;CEDEL_NO
TESTRICU=L;;;;;;;;+4;TEST;;;100;;;01 Jan 2004;;1003;;;;0;;;;;31 Dec 1906;;;;;;;;;"with an inner; semicolon";;;;;;GBP;;;;;;;;;;;;
TEST_AB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"with ""embedded quotes"" here";;;;;;;;;;;;;;;;;;
    
por 06.02.2015 / 20:00
1

Se você gosta de awk :

awk -F' *[."]' '
{
    FName[$2]=1
    RName[$1]=1
    Data[$1,$2]=$3
}
END{
    printf("%s;","RECORDNAME")
    for (f in FName)
        printf ("%s;",f)
    print ""
    for (i in RName){
        printf ("%s",i)
        for (j in FName)
            printf ("%s;",Data[i,j])
        print ""
        }
}' text.file

Saídas:

RECORDNAME;BID_YIELD;PCTCHNG;NAVALUE_1;EUROCLR_NO;ACTIV_DATE;MKT_MKR_NM;PRTY_PRICE;NAV_NETCHN;ASKSIZE;TRDTIM_1;HST_CLOSE;CLOSE_BID;SPARE_NM1;CURRENCY;SPARE_NM2;SPARE_NM3;TRDPRC_1;NAVDATE;DSPLY_NAME;CLOSE_ASK;OPEN_PRC;MATUR_DATE;BCKGRNDPAG;STRIKE_PRC;OFFCL_CODE;ASK_YIELD;ISSUE_PRC;VALOREN_NO;BOND_TYPE;ISSUE_DATE;PUTCALLIND;RDNDISPLAY;BID;MID_PRICE;COUPN_RATE;RECORDTYPE;ASK;NAVALUE;TIMACT;YIELD;NETCHNG_1;PERATIO;SETTLEDATE;HSTCLSDATE;NAVDAT_1;GEN_VAL1;GEN_VAL2;CEDEL_NO;GEN_VAL3;GEN_VAL4;BIDSIZE;TRADE_DATE;
TEST_AB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TESTRICU=L;;;;;;;;;;;;;GBP;;;;;TEST;;;31 Dec 1906;;;1003;;;100;;01 Jan 2004;;;;;+4;;0;;;;;;;;;;;;;;;;
    
por 06.02.2015 / 20:19