2

我想知道是否有人可以用 perl 帮助绝望的新手解决以下问题。我整天都在尝试,但是在工作中使用我的 perl 书时,我似乎在 google 中找不到任何相关的东西......或者也许我真的很愚蠢。

我有一个类似于以下内容的文件:

Bob     April
Bob     April
Bob     March
Mary    August
Robin   December
Robin   April

我追求的输出文件是:

Bob     April April March
Mary    August
Robin   December April

这样它就会按照每个人出现的顺序列出每个月。

我试着把它变成一个散列,但它当然不会让我有重复,所以我想我想为每个名字(在这个例子中,鲍勃、玛丽和罗宾)都有数组。我害怕上传我一直在尝试调整的代码,因为我知道这将是非常错误的。我想我需要定义(?)数组。这是正确的吗?

任何帮助将不胜感激,我保证在此期间我将更多地研究 perl。

感谢您的时间、耐心和帮助。

#!/usr/bin/perl -w

while (<>) {
    chomp;
    if (defined $old_name) {
        $name=$1;
        $month=$2;
        if ($name eq $old_name) { 
            $array{$month}++;   
            }
        else { 
            print "$old_name";
            foreach (@array)  { 
                push (@array, $month);
                print "\t@array";
                }
            print "\n";
            @array=(); 
            $array{$month}++; 
            }
        }
    else { 
        $name=$1;
        $month=$2;
        $array{month}++;
        }
    $old_name=$name; 
    }
print "$old_name"; 
foreach (@array)  {
    push (@array, $month);
    print "\t@array";
    }
print "\n";
4

4 回答 4

2

对于这样一个简单的任务,您的代码看起来过于复杂。

use strict;
use warnings;

my %hash;
while (<DATA>) {
    my ($name, $mon) = split;
    push @{$hash{$name}}, $mon;
}

for my $name (keys %hash) {
    my @months = @{$hash{$name}};
    print "$name\t@months\n";
}    
__DATA__
Bob     April
Bob     April
Bob     March
Mary    August
Robin   December
Robin   April
于 2012-04-14T14:59:43.300 回答
1

你有点接近。您确实希望使用名称作为键的散列,但是正如您所看到的,对于每个要存储月份数组的名称,因此您要使用的数据结构是数组的散列(或者更确切地说是数组引用, 因为这是在 Perl 中实现的)

在此过程中,请不要养成使用全局变量的习惯 - 100% 的代码应该以“ use strict; use warnings;”开头,以及局部作用域 ( my) 变量。

use strict;
my %data;
my @sorted_names; # Only needed if you care which order to print the results
while (<>) {
    chomp;
    my ($name, $month) = split(/s+/);
    if (! $data{$name}) {
        # Initialize to empty array reference if first time. 
        # Not required - perl will do it for you
        $data{$name} ||= []; 
        # Only needed if you want to print results in the same order of names as input.
        push @sorted_names, $name;
    }
    push @{ $data{$name} }, $month;
}

foreach my $name (@sorted_names) {
    print "$name\t" . join(" ", @{ $data{$name} }) . "\n";
}
# If don't care about name order, just do "foreach my $name (keys %data) {"
于 2012-04-14T15:20:52.097 回答
1

脚本:

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

my %content;
open my $fh, '<file.txt' or die $!;
while (<$fh>) {
  push @{$content{$1}}, $2 if /^(\S+)\s+(\S+)\s*$/;
}
close $fh;
foreach (keys %content) {
  print $_, "\t";
  foreach my $item (@{$content{$_}}) {
    print "$item ";
  }
  print "\n";
}

或者

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

my %content;
open my $fh, '<file.txt' or die $!;
while (<$fh>) {
  push @{$content{$1}}, $2 if /^(\S+)\s+(\S+)\s*$/;
}
close $fh;
print "$_\t@{$content{$_}}\n" for keys %content;

或者

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

my %content;
open my $fh, '<file.txt' or die $!;
s/^(\S+)\s+(\S+)\s*$/{push @{$content{$1}}, $2}/e for <$fh>;
close $fh;
print "$_\t@{$content{$_}}\n" for keys %content;

输出:

Bob     April April March 
Mary    August 
Robin   December April 

对于file.txt包含内容的文件:

Bob     April
Bob     April
Bob     March
Mary    August
Robin   December
Robin   April
于 2012-04-14T23:17:05.643 回答
0

一个简单的方法是使用 perl 的 push 和 pop 函数。(因为你开始使用 perl:http ://perldoc.perl.org/functions/pop.html,http : //perldoc.perl.org/functions /push.html)你应该为每个名字(例如@bobmonths)保留一个全局数组,并在每次找到一个时推送一个月。完成后,打印出名称和数组:

while(<>)
{
chomp;
push(@bobmonths, $2)

...
}
print @bobmonths
于 2012-04-14T15:00:54.680 回答