私は初心者の Unix ユーザーです。2 列のファイルを行形式のデータ ファイルに変換しようとしています。
サンプル データ ファイル: ヘッダー数: 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
私の側で何か必要なことがあればお知らせください。私は Unix 用の PUTTY、64 ビット Intel Core i5-5300U CPU、2.30GHz を使用しています。
これについて助けていただけませんか。とても助かります。
よろしく、ナレシュ
答え1
各入力レコードのフィールド数は一定ではないため、コード内で列名をハードコードしなくて済むように、2 パス アプローチが必要です。
$ 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";
第二に、変数を割り当てて、実行した方法で印刷することはできないため、これを修正する必要があります。
3番目に、Dn = "Date" であり、レコードのフィールドが "date" であるため、"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