Проблема сложная, но не неразрешимая.Мне кажется, что курс всегда будет содержать пробел между альфа-кодом и числовым кодом, и что имена проф также всегда будут содержать пробел.Но тогда вы в значительной степени облажались, если у кого-то есть фамилия из двух частей, например "VAN DYKE".
Регулярное выражение описывает эту запись:
my $record_exp
= qr{ ^ \s*
(\d{4}/\d{2}) # yyyy/mm date
\s+
(\d+) # any number of digits
\s+
(\S+ \s \S+) # non-space cluster, single space, non-space cluster
\s+
# sames as last, possibly not there, separating spaces are included
# in the conditional, because we have to make sure it will start
# right at the next rule.
(?:(\S+ \s \S+)\s+)?
# a cluster of alpha, single space, cluster of digits
(\p{Alpha}+ \s \d+)
\s+ # any number of spaces
(\S+) # any number of non-space
\s+ # ditto..
(\S+)
\s+
(\S+)
}x;
Что делает циклнамного проще:
while ( <$input> ) {
my @fields = m{$record_exp};
# ... list of semantic actions here...
}
Но вы также можете хранить его в структурах, зная, что единственная переменная часть данных - это profs:
use strict;
use warnings;
my @records;
<$input>; # bleed the first line
while ( <$input> ) {
my @fields = split; # split on white-space
my $record = { date => shift @fields };
$record->{session} = shift @fields;
$record->{profs} = [ join( ' ', splice( @fields, 0, 2 )) ];
while ( @fields > 5 ) {
push @{ $record->{profs} }, join( ' ', splice( @fields, 0, 2 ));
}
$record->{course} = splice( @fields, 0, 2 );
@$record{ qw<sec grade count> } = @fields;
push @records, $record;
}