【发布时间】:2012-11-26 22:17:45
【问题描述】:
我想在 unix 中重新格式化数据,将第 2-3 列创建一个新列(在示例中称为 when),但我无法弄清楚如何执行此操作。在不更改作为数据标识符的第 4-7 列的情况下,我想打印第 2 列的第 3 列中指定的次数,然后打印一个值(在本例中为 31)N(= 每个标识符的第 1 列) 减去(每个标识符的第 3 列的总和)次数。因此,重新格式化的数据对于每个标识符将总共有 N 行。 开始的数据如下所示:
N time awake line sex temp rep
9 15 1 188 f 25 1
9 20 1 188 f 25 1
9 21 1 188 f 25 1
9 28 1 188 f 25 1
10 12 1 205 m 25 1
10 14 3 205 m 25 1
10 16 1 205 m 25 1
10 18 1 205 m 25 1
10 19 2 205 m 25 1
10 22 1 205 m 25 1
10 24 1 205 m 25 1
重新格式化的数据应该看起来像这样:
line sex temp rep when
188 f 25 1 15
188 f 25 1 20
188 f 25 1 21
188 f 25 1 28
188 f 25 1 31
188 f 25 1 31
188 f 25 1 31
188 f 25 1 31
188 f 25 1 31
205 m 25 1 12
205 m 25 1 14
205 m 25 1 14
205 m 25 1 14
205 m 25 1 16
205 m 25 1 18
205 m 25 1 19
205 m 25 1 19
205 m 25 1 22
205 m 25 1 24
我的猜测是它需要某种循环,我认为伪代码看起来像这样:
for (each columns 4-7)
tot = (column 1)
rem = tot - sum (column 3)
for (i=0; i <= column 3; i++)
print column 2"\n"
for (j=0; i <= rem; j++)
print "31\n"
非常感谢任何帮助!
编辑添加: 我已经尝试从下面的@mvp 修改 perl 代码,但这并不完全正确。我使用 awk 将原始列 4-7 重新格式化为一个名为 id 的字段(和变量)。有cmets吗?
print "id when\n"; # output header
my $temp='188.f.25.1';
my $count;
my $rest;
my $total;
while(my $input = <>) {
my ($n, $time, $awake, $id)
= split /\s+/, $input; # read each line
next if $n eq 'N'; # skip input header line
if ($id eq $temp) {
$count++;
for (1..$awake) {print "$id $time\n";}
$total = $n;
next;
}
else {
$rest=$total-$count;
for (1..$rest) {print "$temp 31\n";}
}
$count=0;
$temp = $id;
next;
}
以及修改后的输入文件:
N time awake line.sex.temp.rep
9 15 1 188.f.25.1
9 20 1 188.f.25.1
9 21 1 188.f.25.1
9 28 1 188.f.25.1
10 12 1 205.m.25.1
10 14 3 205.m.25.1
10 16 1 205.m.25.1
10 18 1 205.m.25.1
10 19 2 205.m.25.1
10 22 1 205.m.25.1
10 24 1 205.m.25.1
10 10 1 206.m.25.1
10 14 1 206.m.25.1
10 18 1 206.m.25.1
10 20 1 206.m.25.1
10 24 1 206.m.25.1
10 26 1 206.m.25.1
10 27 1 206.m.25.1
10 28 2 206.m.25.1
【问题讨论】:
-
那么对于新的数据格式,你想要的输出是什么?
-
@Kenosis 所需的输出实际上是相同的,除了最初所需的原始输出的前四列将是一个由句点分隔的单个字段,我会使用 awk 重新分隔(由于我是新手,无法真正弄清楚如何一次完成所有操作)