2016-12-31 135 views
1

为十进制我有150列,其中样品的下面::转换科学记数法中的csv

id,c1,c2,c3,c4,c5... 
1,0,acc,123.4E+03,0,bdd,... 
2,1.299E-05,bef,1.666E-08,23,ghh.... 

给出为u可以看到一些字段具有在科学记数法的值大的csv文件(其考虑到csv文件已超过50亿行),所有列都有科学记号中的值是未知的。

我需要将科学记数法中的值转换为其对应的小数形式。 我遇到了以下解决方案:Convert scientific notation to decimal in multiple fields并获得下面的代码:

#!/usr/bin/awk -f 
BEGIN { 
d = "[[:digit:]]" 
OFS = FS = "," 
} 
{ 
delim = "" 
for (i = 1; i <= NF; i++) { 
    if ($i ~ d "E+" d d d "$") { 
     printf "%s%.41f", delim, $i 
    } 
    else { 
     printf "%s%s", delim, $i 
    } 
    delim = OFS 
} 
printf "\n" 
} 

但上面的脚本是不是为我工作。上面的脚本按原样返回我的输入文件(对于E +值和E-值),无需转换。我对shell脚本相当陌生,有什么想法?

我执行脚本以这种形式:

chmod u+x awkscript.awk 
./awkscript.awk inputfile.csv 
+0

如果因为重复而关闭,请至少将'CONVFMT'解决方案复制到上面链接的文章中。 –

+0

csv从哪里来? Excel xlsx,数据库?也许你可以改变单元格格式或导出选项,避免数字格式。你甚至可能赢得额外的精度。 –

回答

3

这可能会帮助你

输入

$ cat f 
id,c1,c2,c3,c4,c5... 
1,0,acc,123.4E+03,0,bdd,... 
2,1.299E-05,bef,1.666E-08,23,ghh.... 

输出

$ awk 'BEGIN{CONVFMT="%.9f"; FS=OFS=","}{for(i=1; i<=NF; i++)if($i~/^[0-9]+([eE][+-][0-9]+)?/)$i+=0;}1' f 
id,c1,c2,c3,c4,c5... 
1,0,acc,123400,0,bdd,... 
2,0.000012990,bef,0.000000017,23,ghh.... 

man awk

的数值表达式通过用sprintf的替换EXPR(CONVFMT,表达式),除非expr可以在主机上被表示为一个准确的整数然后它被转换成的sprintf(“%转换成字符串d“,expr)。 Sprintf()是一个内置的AWK,它复制了sprintf(3)的功能,而CONVFMT是一个内置变量,用于从数字到字符串的内部转换,并初始化为“%.6g”。可以强制显式类型转换,expr“”是字符串,expr+0是数字。

所以你可以在开始或格式字段安排CONVFMT变量。

+0

我尝试用'$ i = sprintf(“%。9f”,$ i)解决这个问题,但是这给我留下了更多的噪音,例如'123400.000000000'。如果从例如'0.000012990'去除尾部零,任何理智的方法?我用'gensub'玩弄,但那只是Gnu awk。 –

+0

@Akshay:辉煌的哥们。你解决了它。非常感谢。对不起,以前没有回复,我们有一个黑屏,所有线路都关闭了。 – Zaire

相关问题