如何在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
我正在处理一些数据文件,其中数据是由 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