Преобразование файла данных из 2 столбцов в формат строки

Преобразование файла данных из 2 столбцов в формат строки

Я начинающий пользователь Unix, пытаюсь преобразовать файл, содержащий 2 столбца, в файл данных строкового формата.

Пример файла данных: HEADER Количество: 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

Ниже приведен код, который я попробовал, но я не получил желаемого результата.

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

Дайте мне знать, если с моей стороны что-то потребуется. Я использую PUTTY для Unix, 64-битный процессор Intel Core i5-5300U, 2,30 ГГц.

Не могли бы вы мне помочь с этим? Я был бы очень полезен.

С уважением, Нареш.

решение1

Поскольку в каждой входной записи нет постоянного количества полей, необходим двухпроходный подход, чтобы избежать необходимости жесткого кодирования имен столбцов в коде:

$ 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

Чтобы использовать указанный выше скрипт awk в скрипте оболочки:

#!/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 ...

решение2

Прежде всего, в вашем коде есть синтаксические ошибки.

Одинарные кавычки в вашем BEGINблоке должны быть двойными

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

Во-вторых, вы не можете назначать переменные и печатать так, как вы это сделали, и это требует исправления.

В-третьих, Dn = «Дата», а поле в ваших записях — «дата», и у вас та же проблема с «DOJ»/«JOD».

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

Эти исправления в BEGINблоке позволят вам...

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

Что происходит из-за логических ошибок.

Как указывает @pLumo, в ваших наборах данных отсутствуют поля данных, и ваш код не позволяет этого сделать, более того, awkон печатает в каждой записи (в каждой строке), а не в каждом наборе записей (непосредственно перед появлением empid).

Есть много способов снять шкуру с этого конкретного кота, но поскольку я сегодня в хорошем настроении, вот простой способ, который поможет новичку изучить массивы...

В BEGINблоке загрузите массив с нужными вам номерами полей, используя имена полей в качестве индексов, и выведите заголовки.

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"
    }

если первое поле - "empid" и &&это не первая запись NR>1, то выполните итерацию по массиву, который будет содержать значения ваших полей (массив пуст, поэтому NR==1мы его пропускаем), и после того, как вы распечатаете массив, очистите его для повторного использованияdelete

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

Для каждой строки в файле загрузите значение $2в массив значений, fieldиспользуя номер поля, извлеченный из fieldsмассива, который мы построили в BEGINблоке в качестве индекса, на основе имени поля в$1

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

Массив все еще будет загружен ненапечатанными значениями, когда вы дойдете до конца файла, поэтому вам придется напечатать массив в последний раз.

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

Редактировать

Скопировав/вставив этот скрипт в терминал

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

С этим вкладом

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

Выход есть

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 

Связанный контент