首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >打印某一列的值另一列中指定的次数

打印某一列的值另一列中指定的次数
EN

Stack Overflow用户
提问于 2012-11-25 08:50:17
回答 3查看 528关注 0票数 2

我有一些数据想要在unix中重新格式化,取第2-3列来创建一个新列(在示例中调用),但我不知道如何做到这一点。在不改变作为数据标识符的列4-7的情况下,我希望打印列2在列3中指定的次数,然后打印一个值(本例中为31)N (=每个标识符的列1)减去(每个标识符的列3的总和)的次数。因此,对于每个标识符,重新格式化的数据总共有N行。开始的数据如下所示:

代码语言:javascript
运行
复制
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   

重新格式化的数据应该看起来像这样:

代码语言:javascript
运行
复制
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

我的猜测是它需要某种循环,我认为伪代码应该是这样的:

代码语言:javascript
运行
复制
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的字段(和变量)。有什么意见吗?

代码语言:javascript
运行
复制
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;
}

和修改后的输入文件:

代码语言:javascript
运行
复制
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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-26 16:23:25

这里有一种使用awk的方法。它使用未经修改的输入文件。运行方式如下:

代码语言:javascript
运行
复制
awk -f script.awk file{,} | column -t

script.awk的内容

代码语言:javascript
运行
复制
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
    }
}

结果:

代码语言:javascript
运行
复制
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

或者,下面是一行代码:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2012-11-25 09:00:33

我在Perl中是这样做的:

将此文件另存为myscript.pl

代码语言:javascript
运行
复制
#!/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

票数 0
EN

Stack Overflow用户

发布于 2012-11-26 14:22:30

代码语言:javascript
运行
复制
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

或者,您也可以使用以下命令:

代码语言:javascript
运行
复制
perl -F -lane 'for($i=0;($i<$F[2])||($.==1);$i++){print "@F[3,4,5,6,1]";if($.==1){last}}' your_file

测试如下:

代码语言:javascript
运行
复制
> 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

执行:

代码语言:javascript
运行
复制
> 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
> 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13547245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档