将 2 列数据文件转换为行格式

将 2 列数据文件转换为行格式

我是 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、64 位 intel core i5-5300U CPU、2.30GHz 的 PUTTY。

你能帮我解决这个问题吗?我会非常有帮助的。

问候,纳雷什

答案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

要在 shell 脚本中使用上述 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到值数组中fieldfieldsBEGIN$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 

相关内容