Я начинающий пользователь 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