我有想要在unix中重新格式化的数据,使用第2-3列创建一个新列(在示例中调用时),但是我无法弄清楚如何执行此操作。在不更改列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的字段(和变量)。任何意见?
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
答案 0 :(得分:1)
这是使用awk
的一种方式。它使用未修改的输入文件。像:
awk -f script.awk file{,} | column -t
script.awk
的内容:
BEGIN {
print "line sex temp rep when"
}
FNR==NR && NR>1 {
a[$4,$5,$6,$7]+=$3
next
}
FNR>1 {
for (i=1;i<=$3;i++) {
print x=($4 FS $5 FS $6 FS $7), $2
a[$4,$5,$6,$7]--
var++
}
if (a[$4,$5,$6,$7]==0) {
for (i=1;i<=$1-var;i++) {
print x, "31"
}
var=0
}
}
结果:
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
或者,这是单行:
awk 'BEGIN { print "line sex temp rep when" } FNR==NR && NR>1 { a[$4,$5,$6,$7]+=$3; next } FNR>1 { for (i=1;i<=$3;i++) { print x=($4 FS $5 FS $6 FS $7), $2; a[$4,$5,$6,$7]--; var++ } if (a[$4,$5,$6,$7]==0) { for (i=1;i<=$1-var;i++) print x, "31"; var=0 } }' file{,} | column -t
答案 1 :(得分:0)
这就是我在Perl中的表现:
将其另存为myscript.pl
:
#!/usr/bin/perl
use strict;
use warnings;
print "line sex temp rep when\n"; # output header
while(my $input = <>) {
my ($n, $time, $awake, $line, $sex, $temp, $rep)
= split /\s+/, $input;
next if $n eq 'N'; # skip input header line
for (1..$awake) {
print "$line $sex $temp $rep $time\n";
}
}
将其称为myscript.pl <a.txt >b.txt
答案 2 :(得分:0)
perl -F -lane 'if($.==1){print "@F[3,4,5,6,1]"}for($i=0;$i<$F[2];$i++){print "@F[3,4,5,6,1]"}' your_file
或者您也可以使用它:
perl -F -lane 'for($i=0;($i<$F[2])||($.==1);$i++){print "@F[3,4,5,6,1]";if($.==1){last}}' your_file
测试如下:
> cat temp
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
执行:
> perl -F -lane 'if($.==1){print "@F[3,4,5,6,1]"}for($i=0;$i<$F[2];$i++){print "@F[3,4,5,6,1]"}' temp
line sex temp rep time
188 f 25 1 15
188 f 25 1 20
188 f 25 1 21
188 f 25 1 28
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
>