Просто добавлю свой опыт в эту тему. Я конвертирую старую машину Asus P5G41T -MLX для запуска FreeBSD 11.1. Изначально он не мог найти устройство Atheros AR8131 -BL1A. Обновление BIOS решило проблему
.Поскольку у вас нет постоянного количества полей в каждой входной записи, требуется двухпроходный -подход, чтобы избежать использования жестких -имен столбцов кода в вашем коде:
$ 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...
Во-первых, в вашем коде есть синтаксические ошибки.
Одинарные кавычки в блоке 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