ich bin ein Unix-Anfänger und versuche, eine Datei mit zwei Spalten in eine Datendatei im Zeilenformat zu konvertieren.
Beispieldatendatei: HEADER-Anzahl: 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
Unten ist der Code, den ich ausprobiert habe, aber ich erhalte nicht die gewünschte Ausgabe.
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
Lassen Sie mich wissen, ob von meiner Seite etwas erforderlich ist. Ich verwende PUTTY für Unix, 64-Bit Intel Core i5-5300U CPU, 2,30 GHz.
Könnten Sie mir dabei bitte weiterhelfen? Das wäre eine große Hilfe.
Grüße, Naresh
Antwort1
Da Sie nicht in jedem Eingabedatensatz über eine konsistente Anzahl von Feldern verfügen, ist ein zweistufiger Ansatz erforderlich, um zu vermeiden, dass Sie Spaltennamen in Ihrem Code fest codieren müssen:
$ 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
So verwenden Sie das obige Awk-Skript in einem Shell-Skript:
#!/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 ...
Antwort2
Zunächst einmal enthält Ihr Code Syntaxfehler.
Die einfachen Anführungszeichen in Ihrem BEGIN
Block sollten doppelt sein
BEGIN {FS=";";
OFS=";";
RS="\n";
Zweitens können Sie Variablen nicht auf die Art und Weise zuweisen und drucken, wie Sie es getan haben. Dies muss korrigiert werden.
Drittens: Dn = „Datum“ und das Feld in Ihren Datensätzen ist „Datum“ und Sie haben das gleiche Problem mit „DOJ“/„JOD“.
An = "empid"; Bn = "empname"; Cn = "salary"; Dn = "dept"; En = "age"; Fn = "JOD";
print An, Bn, Cn, Dn, En, Fn
}
Diese Korrekturen am BEGIN
Block ermöglichen Ihnen ...
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
Was auf logische Fehler zurückzuführen ist.
Wie @pLumo anmerkt, fehlen in Ihren Datensätzen Datenfelder und Ihr Code lässt dies nicht zu, sondern awk
druckt vielmehr bei jedem Datensatz (jeder Zeile) und nicht bei jedem Datensatzsatz (direkt vor dem Auftreten von empid
).
Es gibt viele Möglichkeiten, dieses Problem zu lösen, aber da ich heute gut gelaunt bin, hier eine einfache Methode, mit der Anfänger Arrays lernen können …
Laden Sie im BEGIN
Block ein Array mit den gewünschten Feldnummern, wobei Sie die Feldnamen als Indizes verwenden, und drucken Sie die Titel
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"
}
Wenn das erste Feld "empid" ist und &&
es nicht der erste Datensatz ist, NR>1
dann iterieren Sie über das Array, das Ihre Feldwerte enthalten wird (das Array ist leer, wenn NR==1
es leer ist, deshalb überspringen wir es) und nachdem Sie das Array gedruckt haben, leeren Sie es zur Wiederverwendung durchdelete
$1=="empid" && NR>1 {
for (f=1; f<6; f++) printf field[f]";"; print field[6]; delete field}
Laden Sie für jede Zeile in der Datei den Wert $2
in Ihr Werte-Array und field
verwenden Sie dabei die Feldnummer aus dem fields
Array, das wir im BEGIN
Block erstellt haben, als Index, basierend auf dem Feldnamen in$1
{field[fields[$1]]=$2
Das Array wird immer noch mit ungedruckten Werten geladen, wenn Sie das Ende der Datei erreichen und Sie müssen das Array ein letztes Mal ausdrucken.
}END{for (f=1; f<6; f++) printf field[f]";"; print field[6]}' file1
Bearbeiten
Mit diesem Skript in das Terminal kopieren/einfügen
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
Mit diesem Eingang
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
Ausgabe ist
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