Perl 按另一列中指定的次数打印一列的值
我有一些数据要在unix中重新格式化,使用第2-3列生成一个新列(在本例中称为when),但我很难弄清楚如何执行此操作。在不更改列4-7的情况下,它们一起作为数据的标识符,我想打印列2第3列中指定的次数,然后打印一个值(在本例中为31)N(=每个标识符的列1)减去(每个标识符的列3的总和)次数。因此,对于每个标识符,重新格式化的数据总共有N行。 要开始的数据如下所示: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
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)。谢谢,我想我终于得到了它,直到现在才意识到数组是如何构造的。非常好!