Soy un usuario principiante de Unix y estoy intentando convertir un archivo que tiene 2 columnas en un archivo de datos con formato de fila.
Archivo de datos de muestra: HEADER Count: 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
A continuación se muestra el código que probé, pero no obtengo el resultado deseado.
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
avíseme si se requiere algo de mi parte. Estoy usando PUTTY para Unix, CPU Intel Core i5-5300U de 64 bits, 2,30 GHz.
¿Podrías ayudarme con esto? Sería de gran ayuda.
Saludos, Naresh
Respuesta1
Dado que no tiene una cantidad constante de campos en cada registro de entrada, se requiere un enfoque de 2 pasos para evitar tener que codificar los nombres de las columnas en su 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 utilizar el script awk anterior en un 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 ...
Respuesta2
En primer lugar, hay errores de sintaxis en su código.
Las comillas simples en tu BEGIN
bloque deben ser dobles.
BEGIN {FS=";";
OFS=";";
RS="\n";
En segundo lugar, no puede asignar variables e imprimir de la forma en que lo ha hecho y esto necesita corrección.
En tercer lugar, Dn = "Fecha" y el campo en sus registros es "fecha" y tiene el mismo problema con "DOJ"/"JOD"
An = "empid"; Bn = "empname"; Cn = "salary"; Dn = "dept"; En = "age"; Fn = "JOD";
print An, Bn, Cn, Dn, En, Fn
}
Estas correcciones al BEGIN
bloque te llevan 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
Lo cual se debe a errores lógicos.
Como señala @pLumo, faltan campos de datos en sus conjuntos de datos y su código no lo permite, pero más aún, awk
se imprime en cada registro (cada línea) y no en cada conjunto de registros (justo antes de que aparezca empid
).
Hay muchas maneras de despellejar a este gato en particular, pero como hoy estoy de buen humor, aquí hay una sencilla para que un principiante aprenda a hacer arreglos....
En el BEGIN
bloque, cargue una matriz con los números de campo que desee utilizando los nombres de los campos como índices e imprima los 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"
}
si el primer campo es "empid" y &&
no es el primer registro NR>1
, entonces repita la matriz que contendrá los valores de su campo (la matriz está vacía cuando NR==1
es por eso que la omitimos) y después de haber impreso la matriz, vacíela para reutilizar pordelete
$1=="empid" && NR>1 {
for (f=1; f<6; f++) printf field[f]";"; print field[6]; delete field}
Para cada línea del archivo, cargue el valor $2
en su matriz de valores field
usando el número de campo recuperado de la fields
matriz que construimos en el BEGIN
bloque como índice, según el nombre del campo en$1
{field[fields[$1]]=$2
La matriz seguirá cargada con valores no impresos cuando llegue al final del archivo, por lo que tendrá que imprimir la matriz por última vez.
}END{for (f=1; f<6; f++) printf field[f]";"; print field[6]}' file1
Editar
Con este script copie/pegue en la 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
Con 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
La salida es
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