在 awk 脚本中保留浮点值小数位

Keeping float value decimal places in an awk script

我有这一行使用 awk:

$ awk '{
                 for (i=1;i<=NF;i++){
                   if ($i+0 != $i)
                     $i = temp[i]+0.00
                   temp[i]=$i+0.00
                }}1'

简而言之,这会将每个单词转换为该列中最后看到的数字。

问题

问题是来自 $i = temp[i]+0.00 的每个值的小数位都失去了小数精度。

例如,

-ERROR -1.57 -2.02 
-2.10 2.70 ERROR
-4.70 ERROR -0.52 
-2.20 ERROR -0.02 
-2.20 -1.50 ERROR

变成:

0 -1.57 -2.02 
-2.10 2.70 -2.02
-4.70 2.7 -0.52 
-2.20 2.7 -0.02 
-2.20 -1.50 -0.02

2.70 会变成 2.7,所以 2.70 后面的每个单词都不会变成 2.70,而是变成 2.7。如何强制 awk 将浮点值保存到设定的小数位数?

显然,+0.00 没有帮助。

避免对值进行数学计算,这反过来又会导致 awk 无法决定要保持多少位精度;相反,只需按原样保存每个值(有效地保存为字符串)。

考虑:

$ printf "1 1.1 1.02 1.003 1.0004 1.00005\na b c d e f\n" 
1 1.1 1.02 1.003 1.0004 1.00005
a b c d e f

对 OP 当前 awk 代码的一些调整:

$ printf "1 1.1 1.02 1.003 1.0004 1.00005\na b c d e f\n" | awk '
{ for (i=1;i<=NF;i++){
      if ($i+0 != $i)
         $i = (i in temp ? temp[i] : 0)
      temp[i]=$i
   }
} 1'
1 1.1 1.02 1.003 1.0004 1.00005
1 1.1 1.02 1.003 1.0004 1.00005

回到 OP 的示例数据 ...

向示例数据集添加更多行:

$ cat sample.dat
-ERROR -1.57 -2.02
-2.10 2.70 ERROR
-4.70 ERROR -0.52
-2.20 ERROR -0.02
-2.20 -1.50 ERROR
-3.333 0.1234 -0.02
ERROR ERROR ERROR
-2.10 2.70 ERROR
-4.70 ERROR -0.52

运行修改后的awk代码:

awk '
{ for (i=1;i<=NF;i++){
      if ($i+0 != $i)
         $i = (i in temp ? temp[i] : 0)
      temp[i]=$i
   }
}1' sample.dat

这会生成:

0 -1.57 -2.02
-2.10 2.70 -2.02
-4.70 2.70 -0.52
-2.20 2.70 -0.02
-2.20 -1.50 -0.02
-3.333 0.1234 -0.02
-3.333 0.1234 -0.02
-2.10 2.70 -0.02
-4.70 2.70 -0.52

如果这不能解决问题,那么我们将需要查看更多样本数据以更准确地重现该问题。

使用您显示的示例,请尝试以下 awk 代码。

awk '
{
  val=""
  for(i=1;i<=NF;i++){
    if(int($i)){
      val=(val?val OFS:"") $i
      arr[i]=$i
    }
    else{
      val=(val?val OFS:"") (i in arr?arr[i]:0)
    }
  }
  print val
}
'  Input_file