我有一个如下文件。
1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2
依旧......
一个人(1111)每行可以有一个产品。我需要输出如下
1111|row1|p1|p2|p3|p4|p5
1111|row2|p6
2222|p1|p2
3333|p1|p2|p3
所以对于一行只允许到p5,剩下的应该在第2行。 请帮我在Perl中以这种方式获得输出。
答案 0 :(得分:4)
使用数组散列来存储每个人的产品:
#!/usr/bin/perl
use warnings;
use strict;
my %owns;
while (<DATA>) {
chomp;
my ($person, $product) = split /\|/;
push @{ $owns{$person} }, $product;
}
for my $person (keys %owns) {
my @products = @{ $owns{$person} };
if (@products > 5) {
my $row = 1;
while (@products) {
my @five = splice @products, 0, 5;
print join '|', $person, "row$row", @five;
print "\n";
$row++;
}
} else {
print join '|', $person, @products;
print "\n";
}
}
__DATA__
1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2
答案 1 :(得分:0)
没有什么比试图聪明的程序员更糟糕了。
但是,以下使用正则表达式来执行相同的过滤器:
use strict;
use warnings;
my $data = do {local $/; <DATA>};
$data =~ s{^((\d+)\|.*\n(?:\2\|.*\n)+)}{
my ($whole, $header) = ($1, $2);
my @nums = map {/\|(.*)/} split "\n", $whole;
my $return = '';
if (@nums > 5) {
for (my $i = 1; @nums; $i++) {
$return .= join('|', $header, "row$i", splice @nums, 0, 5) . "\n";
}
} else {
$return = join('|', $header, @nums) . "\n";
}
$return;
}emg;
print $data;
__DATA__
1111|p1
1111|p2
1111|p3
1111|p4
1111|p5
1111|p6
2222|p1
2222|p2
输出:
1111|row1|p1|p2|p3|p4|p5
1111|row2|p6
2222|p1|p2