Не используйте регулярные выражения для этого.Это похоже на формат с фиксированной колонкой, поэтому распаковка будет намного быстрее.
Вот пример программы, показывающей суть проблемы.Вам все равно придется выяснить, как его интегрировать, чтобы вы знали, когда начинается новая запись о человеке, и так далее.Я сделал так, чтобы формат для распаковки значений исходил в основном из заголовков, чтобы вам не приходилось тратить так много времени на подсчет столбцов (но также и для того, чтобы он легко реагировал на изменения в положениях столбцов):
chomp( my $header = <DATA> );
my( $num, $name, $rest ) = unpack "a2 a20 a*", $header;
my @grades = split /(?=\s+)/, $rest;
my @grade_keys = map { /(\S+)/} @grades;
my $format = 'a13 a4 a5 ' . join ' ', map { 'a' . length } @grades;
while( <DATA> ) {
my( $key, $label, $number, @grades ) = unpack $format, $_;
$$_ =~ s/\s//g foreach ( \$key, \$label, \$number );
@{ $hash{$key}{$label}{$number} }{@grade_keys} =
map { s/\s//g; $_ } @grades;
}
use Data::Dumper;
print Dumper( \%hash );
Вы говорите, что у вас проблема, потому что некоторые столбцы имеют значения с тремя цифрами.Если это не смещает сетку, поэтому младшая значащая цифра не совпадает с последним непробельным символом в столбце, этот код должен работать.
Вот структура данных, которую я создал для "AOZSVIN, TAMSSZ B" (чьи данные образца теперь скрыты в редактировании вашего вопроса), хотя вы можете расположить их так, как вам нравится:
$VAR1 = {
'0' => {
'BIOS' => {
'206' => {
'F' => '6',
'AU' => '',
'FS' => '',
'B-' => '9',
'D+' => '3',
'CR' => '',
'B+' => '5',
'WP' => '7',
'C+' => '8',
'NR' => '',
'C' => '4',
'PR' => '',
'A' => '3',
'W' => '',
'I*' => '',
'A-' => '14',
'P' => '',
'WF' => '',
'B' => '11',
'FN' => '',
'D' => '1',
'D-' => '1',
'I' => '',
'C-' => '8'
}
},
'AAS' => {
'353' => {
'F' => '2',
'AU' => '',
'FS' => '',
'B-' => '6',
'D+' => '',
'CR' => '',
'B+' => '5',
'WP' => '',
'C+' => '',
'NR' => '',
'C' => '1',
'PR' => '',
'A' => '2',
'W' => '',
'I*' => '',
'A-' => '3',
'P' => '',
'WF' => '',
'B' => '2',
'FN' => '',
'D' => '',
'D-' => '',
'I' => '',
'C-' => ''
},
'150' => {
'F' => '4',
'AU' => '',
'FS' => '',
'B-' => '45',
'D+' => '2',
'CR' => '',
'B+' => '16',
'WP' => '4',
'C+' => '14',
'NR' => '',
'C' => '8',
'PR' => '',
'A' => '23',
'W' => '',
'I*' => '',
'A-' => '25',
'P' => '',
'WF' => '',
'B' => '35',
'FN' => '',
'D' => '1',
'D-' => '1',
'I' => '',
'C-' => '10'
}
},
'T304' => {
'480M' => {
'F' => '',
'AU' => '',
'FS' => '1',
'B-' => '2',
'D+' => '',
'CR' => '',
'B+' => '8',
'WP' => '',
'C+' => '3',
'NR' => '',
'C' => '2',
'PR' => '',
'A' => '3',
'W' => '',
'I*' => '',
'A-' => '10',
'P' => '',
'WF' => '1',
'B' => '8',
'FN' => '',
'D' => '',
'D-' => '',
'I' => '',
'C-' => '1'
}
}
}
};
А для вашего нового образца "Palmer, Jan":
$VAR1 = {
'0' => {
'ECON' => {
'103' => {
'F' => '35',
'AU' => '1',
'FS' => '',
'B-' => '1',
'D+' => '',
'CR' => '',
'B+' => '35',
'WP' => '10',
'C+' => '14',
'NR' => '',
'C' => '75',
'PR' => '',
'A' => '98',
'W' => '',
'I*' => '',
'A-' => '',
'P' => '',
'WF' => '',
'B' => '114',
'FN' => '',
'TOTAL' => '',
'D' => '9',
'D-' => '',
'I' => '1',
'C-' => ''
}
}
}
};