【问题标题】:Convert Scientific notation to decimal in csv [duplicate]在csv中将科学记数法转换为十进制[重复]
【发布时间】:2017-05-15 07:28:24
【问题描述】:

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

【问题讨论】:

  • 如果因为重复而被关闭,请至少将CONVFMT 解决方案复制到上面链接的帖子中。
  • csv 是从哪里来的? Excel xlsx,数据库?也许您可以更改单元格格式或导出选项,避免使用数字格式。您甚至可能赢得额外的精确度。

标签: bash shell csv awk


【解决方案1】:

这可能对你有帮助

输入

$ 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

通过将 expr 替换为 sprintf(CONVFMT, 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。
  • @Akshay:很棒的伙伴。你解决了。非常感谢。很抱歉没有早点回复,我们停电了,所有线路都断了。
  • 该命令不适用于负数。添加[-]? 来解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 2012-11-29
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2018-11-27
相关资源
最近更新 更多