将CSV文件中的科学计数法转换为十进制

3
我可以帮助您进行翻译。以下是需要翻译的内容:

我有一个包含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....

正如您所看到的,一些字段的值是科学计数法表示的(考虑到CSV文件具有50亿行,不知道所有列的值是否都是以科学计数法表示)。

我需要将科学计数法表示的值转换为相应的十进制形式。 我找到了以下解决方案:在多个字段中将科学计数法转换为十进制 并获得了以下代码:

#!/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

如果此问题因为重复而被关闭,请至少将“CONVFMT”解决方案复制到上面链接的帖子中。 - James Brown
CSV文件来自哪里?Excel xlsx,数据库?也许您可以更改单元格格式或导出选项,避免使用数字格式。这样甚至可以获得额外的精度。 - Walter A
1个回答

5

This may help you

Input

$ 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(CONVFMT, expr) 替换 expr 来转换为字符串,除非 expr 可以在主机上表示为精确整数,那么它将被转换为 sprintf("%d", expr)。Sprintf() 是一个 AWK 内置函数,可以复制 sprintf(3) 的功能,CONVFMT 是一个内置变量,用于从数字到字符串的内部转换,并初始化为 "%.6g"。可以强制进行显式类型转换,expr "" 为字符串,expr+0 为数字。

因此,您可以在开头或格式字段中安排 CONVFMT 变量。


我尝试使用$i=sprintf("%.9f", $i)来解决这个问题,但是这样会留下更多的噪音,例如123400.000000000。有什么明智的方法可以从0.000012990中删除尾随的零吗?我玩弄了一下gensub,但那只适用于Gnu awk。 - James Brown
@Akshay:太棒了,伙计。你解决了它。非常感谢。很抱歉之前没有回复,我们停电了,所有线路都断了。 - Zaire
该命令不支持负数。添加[-]?以解决此问题。 - s.ouchene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接