如何在bash中将space分隔的键值数据转换成CSV格式?

How to convert space separated key value data into CSV format in bash?

我正在处理一些数据文件,其中数据是由 space 分隔的键值对。

文件中的数据不一致。所有键和值并不总是 present.But 键将始终为 Table、计数和大小。

下面的示例有 table_name、数量、尺寸信息

cat sample1.txt
Table SCOTT.TABLE1 count 3889 size 300
Table SCOTT.TABLE2 count 7744
Table SCOTT.TABLE3 count 2622
Table SCOTT.TABLE4 size 2773 count 22
Table SCOTT.TABLE5 size 21

以下文件只有 table_name 但没有数量和尺寸数据。

cat sample2.txt
Table SCOTT.TABLE1
Table SCOTT.TABLE2
Table SCOTT.TABLE3
Table SCOTT.TABLE4
Table SCOTT.TABLE5

所以我尝试使用以下方法将这些文件转换为 CSV 格式

cat <file_name> | awk -F' ' 'BEGIN { RS="\n"; print"Table,Count,Size";OFS=","  } NR > 1 { print a["Table"], a["count"], a["size"]; delete a; next }{ a[]= }{ a[]= }{ a[]= }'

cat sample1.txt | awk -F' ' 'BEGIN { RS="\n"; print"Table,Count,Size";OFS=","  }
NR > 1 { print a["Table"], a["count"], a["size"]; delete a; next }
{ a[]= }{ a[]= }{ a[]= }'

Table,Count,Size
SCOTT.TABLE1,3889,300
,,
,,
,,

第二个样本

cat sample2.txt | awk -F' ' 'BEGIN { RS="\n"; print"Table,Count,Size";OFS=","  } NR > 1 { print a["Table"], a["count"], a["size"]; delete a; next }{ a[]= }{ a[]= }{ a[]= }'
Table,Count,Size
SCOTT.TABLE1,,
,,
,,
,,

但预计如下:

对于sample1.txt

TABLE,count,size
SCOTT.TABLE1,3889,300
SCOTT.TABLE2,7744,
SCOTT.TABLE3,2622
SCOTT.TABLE4,22,2773
SCOTT.TABLE5,,21

对于sample2.txt

Table,Count,Size
SCOTT.TABLE1,,
SCOTT.TABLE2,,
SCOTT.TABLE3,,
SCOTT.TABLE4,,
SCOTT.TABLE5,,

提前致谢。

这是一个不优雅但快速且易于理解的解决方案:

awk 'BEGIN{OFS=",";print "TABLE,count,size"}
  {
    t=
    if(=="count"){
      c=
      s=
    }
    else{
      s=
      c=
    }
    print t,c,s
  }' 1.txt

输出:

TABLE,count,size
SCOTT.TABLE1,3889,300
SCOTT.TABLE2,7744,
SCOTT.TABLE3,2622,
SCOTT.TABLE4,22,2773
SCOTT.TABLE5,,21

awk 救援!

$ awk -v OFS=',' '{for(i=1;i<NF;i+=2) 
                     {if(!($i in c)){c[$i];cols[++k]=$i};
                      v[NR,$i]=$(i+1)}} 
               END{for(i=1;i<=k;i++) printf "%s", cols[i] OFS; 
                   print ""; 
                   for(i=1;i<=NR;i++) 
                     {for(j=1;j<=k;j++) printf "%s", v[i,cols[j]] OFS;
                      print ""}}' file

Table,count,size,
SCOTT.TABLE1,3889,300,
SCOTT.TABLE2,7744,,
SCOTT.TABLE3,2622,,
SCOTT.TABLE4,22,2773,
SCOTT.TABLE5,,21,

如果您有 gawk,您可以使用 sorted-in

进一步简化它

UPDATE 对于修订后的问题,header 需要提前知道,因为密钥可能会完全丢失。这简化了问题,下面的脚本应该可以解决问题。

$ awk -v header='Table,count,size' \
      'BEGIN{OFS=","; n=split(header,h,OFS); print header} 
            {for(i=1; i<NF; i+=2) v[NR,$i]=$(i+1)} 
         END{for(i=1; i<=NR; i++) 
               {printf "%s", v[i,h[1]]; 
                for(j=2; j<=n; j++) printf "%s", OFS v[i,h[j]]; 
                print ""}}' file