perl:列中的反向值

use*_*607 -1 perl

我有一个带有4列的制表符分隔表(table1),看起来像这样

A       +       1      1
A       +       2      2
A       +       3      3
B       -       2      4
B       -       3      5
B       -       4      6
B       -       5      7
C       +       1      8
C       +       2      9
C       +       3      10
D       -       1      11
D       -       2      12
D       -       3      13
Run Code Online (Sandbox Code Playgroud)

col1中的字母定义组.现在,如果col2中有一个"+",我只想保持原样.如果在col2中有" - ",我想要反转col3中的值,对于属于col1定义的组的所有行.对于此示例,输出应如下所示

A       +       1       1
A       +       2       2
A       +       3       3
B       -       5       4
B       -       4       5
B       -       3       6
B       -       2       7
C       +       1       8
C       +       2       9
C       +       3       10
D       -       3       11
D       -       2       12
D       -       1       13
Run Code Online (Sandbox Code Playgroud)

所以对于A组来说,一切都保持不变.但对于B组,col3中的原始值为:2,3,4,5.它们应该变为5,4,3,2.其余列保持不变.

我应该如何在Perl中解决这个问题?

cho*_*oba 5

-组的行保留在缓冲区中,在组更改时输出.

#!/usr/bin/perl
use warnings;
use strict;

sub output {
    my $buffer = shift;
    my @rev = map $_->[2], @$buffer;
    $_->[2] = pop @rev for @$buffer;  # Reverse the 3rd column.
    print join("\t", @$_) for @$buffer;
    @$buffer = ();
}

my @buffer;
my $group;
print scalar <>; # header
while (<>) {
    my @cols = split /\t/;

    if (@buffer and $cols[0] ne $group) {
        output(\@buffer);
    }

    if ('+' eq $cols[1]) {
        print;
    } else {
        $group = $cols[0];
        push @buffer, \@cols;
    }
}
output(\@buffer) if @buffer;  # Don't forget to output the last buffer.
Run Code Online (Sandbox Code Playgroud)