更改数据文件的双精度

时间:2015-09-01 09:34:57

标签: linux awk double precision data-files

我有一百个带三个字段的文件。每个人都看起来像这样(有更多行):

#time data1 data2
20 1.9864547484940e+01 -3.96363547484940e+01
40 2.164547484949e+01 -3.2363547477060e+01 
60 1.9800047484940e+02 -4.06363547484940e+02
…

它们很重,有些需要1.5G。我想通过以较低的双精度保存最后两列并删除e+0?项来减小它们的大小。例如,我想将上面的四行转换为:

#time data1 data2
20 19.865 -39.636
40 21.645 -32.364
60 198.00 -406.36
…

我用Google搜索并遇到CONVFMT的{​​{1}}选项。但我不知道如何使用它,因为我真的不是awk的专家。这是在我的情况下使用的正确工具吗?如果是这样,我应该如何使用它?

我还想过编写一个C ++脚本,但直接命令行会很棒。

2 个答案:

答案 0 :(得分:5)

我会使用awk的printf函数:

awk 'NR==1;NR>1{printf "%d %.3f %.3f\n", $1, $2, $3}' file

以上命令输出:

#time data1 data2
20 19.865 -39.636
40 21.645 -32.364
60 198.000 -406.364

简短说明:

如果我们在第一行( NR ==记录数),

NR==1将评估为true。如果一个条件没有跟着一个动作(在{}之间),awk就会打印一行,在这种情况下是标题。

NR>1在除第一行输入之外的所有其他行上评估为true。接下来是一个动作,它使用printf来实现所需的结果。

答案 1 :(得分:0)

你可以使用coreutils:

var get_object_id = (function() {
  var generated_ids = 1;
  var map = new Map();
  return get_object_id;
  function get_object_id(obj) {
    if (map.has(obj)) {
      return map.get(obj);
    } else {
      var r = generated_ids++;
      map.set(obj, r);
      return r;
    }
  }
})();

function tuple() {
  return Array.prototype.map.call(arguments, get_object_id).join(',');
}

// Test
var data = [{x:3,y:5,z:3},{x:3,y:4,z:4},{x:3,y:4,z:7},
            {x:3,y:1,z:1},{x:3,y:5,z:4}];
var map = new Map();
for (var i=0; i<data.length; i++) {
  var p = data[i];
  var t = tuple(p.x,p.y);
  if (!map.has(t)) map.set(t,[]);
  map.get(t).push(p);
}

function test(p) {
  document.writeln((JSON.stringify(p)+' ==> ' + 
    JSON.stringify(map.get(tuple(p.x,p.y)))).replace(/"/g,''));
}

document.writeln('<pre>');
test({x:3,y:5});
test({x:3,y:4});
test({x:3,y:1});
document.writeln('</pre>');

输出:

head -n1 infile; tail -n+2 infile | while read n1 n2 n3; do printf "%d %.3f %.3f\n" $n1 $n2 $n3; done