Awk 在多个字段中将科学记数法转换为十进制

Awk 在多个字段中将科学记数法转换为十进制,awk,Awk,下面的内容对我在第12列中的数据非常有用,但我有70多列不完全相同,我需要输出所有列,转换后的列替换科学值 awk -F',' '{printf "%.41f\n", $12}' $file 谢谢 这是一行 2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,2.600000000000000e+001,4.152327506554059e+001,-7.8935238066

下面的内容对我在第12列中的数据非常有用,但我有70多列不完全相同,我需要输出所有列,转换后的列替换科学值

 awk -F',' '{printf "%.41f\n", $12}' $file
谢谢

这是一行

2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,2.600000000000000e+001,4.152327506554059e+001,-7.893523806678388e+001,5.447572631835938e+002,2.093000000000000e+003,5.295000000000000e+003,1,194733,1.647400093078613e+001,31047680,1152540,29895140,4738,1.586914062500000e+000,-1.150000000000000e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,3.606000000000000e+003,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,4.557073364257813e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,11,0.000000000000000e+000,2.000000000000000e+000,0,0,0,0,4.466836981009692e-004,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,8,0,840,1,600,1,6,1,1,1,5,2,2,2,1,1,1,1,4854347,0,-
更新

这适用于未转换的输出。由于某种原因,我在插入else-if语句时遇到了一些问题。文件或cli中的所有内容似乎都给了我一个语法错误

awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i == 19||i == 20||i == 21||i == 22|| i == 40|| i == 43||i == 44||i == 45||i == 46||i >= 51) printf ($i",")};}' $file
解决

解决了。谢谢你所有的好主意。我似乎无法使它在带有awk-f的文件中工作,但在命令行上,它工作得很好。我在我的程序里放了一行

awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i >= 19&&i <= 22|| i == 40|| i >= 43&&i <= 46||i >= 51&&i <= 70) printf($i","); else if (i == 10||i == 18) printf("%.2f,", $i); else if (i == 11||i == 12) printf("%.41f,", $i); else if (i == 13) printf("%.1f,", $i); else if (i == 14||i == 15||i >= 24&&i <= 46) printf ("%d,", $i); else if (i == 23) printf("%.4f,", $i); else if (i >= 47&&i <= 50) printf("%.6f,", $i); if (i == 71) printf ($i"\n")};}'

您可以始终循环所有数据字段,并在
printf
中使用它们。对于仅用于测试力学的简单文件,您可以尝试以下方法:

 awk '{for (i=1; i<=NF; i++) printf("%d = %s\n", i, $i);}' data.txt
根据下面的评论更新(不是对系统测试语法):

如果您有某些字段需要区别对待,则可能需要使用语句或语句来区别对待不同的字段。如果您将脚本存储在一个文件中,这将更容易,我们将其称为
so.awk
,并按如下方式调用它:

  awk -f so.awk $file
您的脚本可能包含以下内容:

BEGIN{ FS=',' }
{ for (i=1; i<=NF; i++)
    {
      if (i == 20 || i == 22|| i == 30)
        printf( " .. ", $i)
      else if ( i == 13 || i == 24)
        printf( " ....", $i)
      etc.
    }
}
BEGIN{FS=',}
{for(i=1;i 2)…
或其他范围,以避免在可能的情况下列出每个字段


作为这一系列if语句的替代方法,请参见上述switch语句。

您可以在循环中进行正则表达式匹配,以选择每个字段的格式,因为数字在AWK中也是字符串:

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

如果有更多其他格式的字段(而不是每个字段一个),您可以执行类似于
plainfmt
数组的操作。

我将其更改为此,以获取所需的所有小数点,并反转%d和%s,但有些字段不需要转换,因此它们会失真,有些字段的小数点太多(i=1;i@RoadKing我在我的答案中添加了更多的信息-希望这是有用的。如果你有关于这个问题的更多信息,最好更新你的原始帖子,因为不是每个人都会查看所有的评论,加上评论中的格式不是很好(见代码)。您的
if
语句将导致某些字段打印两到三次。请将
printf
更改为
printf(“…”,$i)
。我想我不明白这一点。..printf(“…”,$i)。它只是为我打印点。@RoadKing您需要为每个要打印的字段在其中添加特定的格式说明。使用if语句的整个想法是,您希望以不同的方式处理不同的字段,即打印不同的字段。因此,由于我不知道您要为给定字段设置什么格式,所以我刚刚离开…请稍候在某些情况下,你可能只需要%s,而在其他情况下,你只需要%.24f等等。只有你知道什么是正确的:)我绝对不会在命令行上这样做。你可能想看看下面的@DennisWilliamson方法,看起来很流畅
cat$file | awk-f~/bin/so.awk awk:./so.awk:16:}awk:./so.awk:16:^语法错误
如果有区别的话,我现在正在windows上使用cygwin。@RoadKing:我忘了关闭
开始
块。请查看我编辑的答案。@RoadKing:我编辑了我的答案。我希望你发现一些新信息有用。是的,这是最好的解决方案。我的代码正在运行。我将合并这是最后的代码。我想我明白了。谢谢
  awk -f so.awk $file
BEGIN{ FS=',' }
{ for (i=1; i<=NF; i++)
    {
      if (i == 20 || i == 22|| i == 30)
        printf( " .. ", $i)
      else if ( i == 13 || i == 24)
        printf( " ....", $i)
      etc.
    }
}
#!/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"
}
#!/usr/bin/awk -f
BEGIN {
    plainlist = "16 17 19 20 21 22 40 43 44 45 46"
    split(plainlist, arr)
    for (i in arr) {
        plainfmt[arr[i]] = "%s"
    }
    OFS = FS = ","
}
{
    delim = ""
    for (i = 1; i <= NF; i++) {
        printf "%s", delim
        if (i <= 9 || i in plainfmt || i >= 51) {
            printf plainfmt[i], $i
        }
        else if (i == 10) {
            printf "%.41f", $i
        }
        else if (i == 12) {
            printf "%.12f", $i
        }
        delim = OFS
    }
    printf "\n"
}