bash - 在csv中将科学记数法转换为十进制

标签 bash shell csv awk

<分区>

我有一个包含 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 亿行,所有列都具有科学记数法的值是未知的)。

我需要将科学计数法中的值转换成相应的十进制形式。 我遇到了以下解决方案: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

最佳答案

这可能对你有帮助

输入

$ 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变量。

关于bash - 在csv中将科学记数法转换为十进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41405666/

相关文章:

linux - 从 hdparm 输出中提取信息

linux - 告诉 Mutt 附加文件(在文件中列出)

shell - 查找包含字符串的行并使用 shell 脚本将值回显到新行

mysql - 从 S3 文件构建临时表到 Redshift

linux - 从以 root 身份运行的 bash 脚本向用户添加 ssh key

bash - CATALINA_OPTS 调试选项

linux - 递归复制和重命名

shell - 如何抑制 shell 脚本错误消息?

python - 使用 python pandas 迭代日期范围

c - c 中的 strtok 有问题