Convertendo arquivo de dados de 2 colunas em formato de linha

Convertendo arquivo de dados de 2 colunas em formato de linha

Sou usuário iniciante de Unix, tentando converter um arquivo com 2 colunas em um arquivo de dados em formato de linha.

Arquivo de dados de amostra: HEADER Contagem: 6, EMPID, EMPNAME,SALARY,DEPT,AGE,JOD

col1;col2

empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
JOD;20170101
empid;2001
salary;5000
dept;XYZ
age;27
JOD;20170303
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
JOD;20180607
empid;1005
empname;NAME
salary;10200
dept;XYZ
JOD;20161212

Abaixo está o código que tentei, mas não estou obtendo a saída desejada.

awk '
BEGIN {FS=';'
       OFS=';'
       RS="\n"
Print An = "empid", Bn = "empname", Cn = "salary", Dn = "Dept", En = "age", Fn = "DOJ"
     }
     {
     A=B=C=D=E=F=" "
     for ( i = 1; i<=NF; i++)
          {
           if($i == An)
                A = $(i+1)
           if($i == Bn)
                B = $(i+1)
           if($i == Cn)
                C = $(i+1)
           if($i == Dn)
                D = $(i+1)
           if($i == En)
                E = $(i+1)
           if($i == Fn)
                F = $(i+1)
             }
            print A, B, C, D, E, F
             }' FILE.txt >New_file.txt

deixe-me saber se algo for necessário da minha parte. estou usando o PUTTY para unix, CPU Intel Core i5-5300U de 64 bits, 2,30 GHz.

Você poderia me ajudar com isso. Eu seria muito útil.

Atenciosamente, Naresh

Responder1

Como você não tem um número consistente de campos em cada registro de entrada, é necessária uma abordagem de duas etapas para evitar a necessidade de codificar nomes de colunas em seu código:

$ cat tst.awk
BEGIN { FS=OFS=";" }
NR==FNR {
    if ( !($1 in colNrs) ) {
        colNrs[$1] = ++numCols
        hdr = (numCols>1 ? hdr OFS : "") $1
    }
    next
}
FNR == 1 { print hdr }
{ colNr = colNrs[$1] }
colNr in vals { prt() }
{ vals[colNr] = $2 }
END { prt() }

function prt(   colNr) {
    for (colNr=1; colNr<=numCols; colNr++) {
        printf "%s%s", vals[colNr], (colNr<numCols ? OFS : ORS)
    }
    delete vals
}

.

$ awk -f tst.awk file file
empid;empname;salary;dept;age;JOD
1001;ABC;3000;ABC;24;20170101
2001;;5000;XYZ;27;20170303
1002;MAN;11000;SCI;30;20180607
1005;NAME;10200;XYZ;;20161212

Para usar o script awk acima em um script de shell:

#!/bin/env bash

... other shell stuff ...

awk '
BEGIN { FS=OFS=";" }
NR==FNR {
    if ( !($1 in colNrs) ) {
        colNrs[$1] = ++numCols
        hdr = (numCols>1 ? hdr OFS : "") $1
    }
    next
}
FNR == 1 { print hdr }
{ colNr = colNrs[$1] }
colNr in vals { prt() }
{ vals[colNr] = $2 }
END { prt() }

function prt(   colNr) {
    for (colNr=1; colNr<=numCols; colNr++) {
        printf "%s%s", vals[colNr], (colNr<numCols ? OFS : ORS)
    }
    delete vals
}
' file file

... other shell stuff ...

Responder2

Primeiro de tudo, existem erros de sintaxe no seu código.

As aspas simples no seu BEGINbloco devem ser duplas

BEGIN {FS=";";
       OFS=";";
       RS="\n";

Em segundo lugar, você não pode atribuir variáveis ​​e imprimir da maneira que fez e isso precisa de correção.

Em terceiro lugar, Dn = "Data" e o campo em seus registros é "data" e você tem o mesmo problema com "DOJ"/"JOD"

        An = "empid"; Bn = "empname"; Cn = "salary"; Dn = "dept"; En = "age"; Fn = "JOD";
        print An, Bn, Cn, Dn, En, Fn
     }

Essas correções no BEGINbloco levam você a ...

empid;empname;salary;dept;age;JOD
1001; ; ; ; ; 
 ;ABC; ; ; ; 
 ; ;3000; ; ; 
 ; ; ;ABC; ; 
 ; ; ; ;24; 
 ; ; ; ; ;20170101
2001; ; ; ; ; 
 ; ;5000; ; ; 
 ; ; ;XYZ; ; 
 ; ; ; ;27; 
 ; ; ; ; ;20170303
1002; ; ; ; ; 
 ;MAN; ; ; ; 
 ; ;11000; ; ; 
 ; ; ;SCI; ; 
 ; ; ; ;30; 
 ; ; ; ; ;20180607
1005; ; ; ; ; 
 ;NAME; ; ; ; 
 ; ;10200; ; ; 
 ; ; ;XYZ; ; 
 ; ; ; ; ;20161212

Isso se deve a erros lógicos.

Como @pLumo aponta, faltam campos de dados em seus conjuntos de dados e seu código não permite isso, mas mais ainda, awkestá imprimindo em cada registro (cada linha) e não em cada conjunto de registros (logo antes da ocorrência de empid).

Há muitas maneiras de esfolar esse gato em particular, mas como estou de bom humor hoje, aqui está uma maneira simples de seguir para um iniciante aprender matrizes....

No BEGINbloco carregue um array com os números dos campos que você deseja usando os nomes dos campos como índices e imprima os títulos

awk -F";" 'BEGIN{
    fields["empid"]=1;
    fields["empname"]=2;
    fields["salary"]=3;
    fields["dept"]=4;
    fields["age"]=5;
    fields["JOD"]=6;
    print "empid;empname;salary;dept;age;JOD"
    }

se o primeiro campo for "empid" e &&não for o primeiro registro NR>1, itere sobre o array que conterá os valores do campo (o array está vazio quando NR==1é por isso que o ignoramos) e depois de imprimir o array, esvazie-o para reutilizar pordelete

    $1=="empid" && NR>1 {
         for (f=1; f<6; f++) printf field[f]";"; print field[6]; delete field}

Para cada linha do arquivo, carregue o valor $2em seu array de valores fieldusando o número do campo recuperado do fieldsarray que construímos no BEGINbloco como um índice, com base no nome do campo em$1

   {field[fields[$1]]=$2

O array ainda será carregado com valores não impressos quando você chegar ao final do arquivo e então você terá que imprimir o array uma última vez

    }END{for (f=1; f<6; f++) printf field[f]";"; print field[6]}' file1

Editar

Com este script copie/cole no terminal

awk -F";" 'BEGIN{
    fields["empid"]=1;
    fields["empname"]=2;
    fields["salary"]=3;
    fields["dept"]=4;
    fields["age"]=5;
    fields["JOD"]=6;
    print "empid;empname;salary;dept;age;JOD"
    }$1=="empid" && NR>1 {
         for (f=1; f<6; f++) printf field[f]";"; print field[6]; delete field}{field[fields[$1]]=$2 
         }END{for (f=1; f<6; f++) printf field[f]";"; print field[6]}' file1

Com esta entrada

empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
JOD;20170101
empid;2001
salary;5000
dept;XYZ
age;27
JOD;20170303
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
JOD;20180607
empid;1005
empname;NAME
salary;10200
dept;XYZ
JOD;20161212

A saída é

empid;empname;salary;dept;age;JOD
1001;ABC;3000;ABC;24;20170101
2001;;5000;XYZ;27;20170303
1002;MAN;11000;SCI;30;20180607
1005;NAME;10200;XYZ;;20161212 

informação relacionada