Perl 按另一列中指定的次数打印一列的值

Perl 按另一列中指定的次数打印一列的值,perl,unix,Perl,Unix,我有一些数据要在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

我有一些数据要在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"
重新格式化的数据应该看起来像这样:

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"
我猜它需要某种循环,我认为伪代码应该是这样的:

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"

以下是我在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";
    }
}
#/usr/bin/perl
严格使用;
使用警告;
打印“行性别临时代表时\n”#输出标题
while(my$input=){
我的($n,$time,$awake,$line,$sex,$temp,$rep)
=拆分/\s+/,$input;
下一步如果$n eq'n'#跳过输入标题行
用于(1..$awake){
打印“$line$sex$temp$rep$time\n”;
}
}
将其命名为
myscript.pl b.txt

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 '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
> 

>perl-F-lane'如果($.==1){print“@F[3,4,5,6,1]”for($i=0;$i这里有一种方法使用
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
    }
}
或者,这里有一个班轮:

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

awk'BEGIN{print”line sex temp rep when“}FNR==NR&&NR>1{a[$4,$5,$6,$7]+=$3;next}FNR>1{for(i=1;我是否介意扩展您的答案以包括如何读取数据文件(我们可以称为a.txt)并输出到重新格式化的文件(b.txt)?增加了用法,请参阅我的修订答案我已经运行了脚本,到目前为止它看起来像是一个部分解决方案。它没有解决打印行以在重新格式化的文件的最后一列中填充值“31”。这是我得到的输出(抱歉,不知道如何正确显示):205米25米1 14 205米25米1 16 205米25米1 18 205米25米1 19 205米25米1 22 205米25米1 24 206米25米10 206米25米1 14 206米25米18 206米25米1 20 206米25米24 206米25米26 206米25米27米25米1 28米25米28我看,我完全错过了那一部分。我可以试着为你添加这一部分,或者你可以自己做——你的伪朋友-代码已经存在:-)啊,如果你能添加它,我会非常感激,同时我会尝试自己做,但我猜我对perl语法的不熟悉会给我带来很大的阻碍。具体来说,我根本不知道如何得到第3列的总和。那么,使用新的数据格式,你想要的输出是什么?@Kenosis,想要的输出实际上是same、 除了最初最初期望输出的前四列是一个由句点分隔的单个字段外,我会使用awk重新分隔(由于我是一个新手,无法真正理解如何一次完成这一切)您介意评论一下这是做什么的吗?:a[$4,$5,$6,$7]---@suegene:没问题;
a[$4,$5,$6,$7]--
只需将包含第4、5、6和7列的多维数组递减(1)。谢谢,我想我终于得到了它,直到现在才意识到数组是如何构造的。非常好!