моя работа очень строга относительно использования чего-либо, что не было предварительно установлено.
Ах, хорошо. Об этом можно много говорить, некоторые из них упоминаются в комментариях. Но я бы оставил это на этом этапе, так как вопрос достаточно ясен и четко сформулирован.
Если ваши данные всегда отображаются, значит все просто. Но я предлагаю также добавить код, который проверяет наличие гремлинов в ваших данных, то есть вещи, которые исключают ручной анализ; предварительная обработка сортов. Так что вы получите предупреждение, когда это произойдет.
Сказав это, и с хорошим использованием форматов в другом ответе, я хотел бы прокомментировать код.
Проблема в том, что строка
push @data, @fields;
оценивает @fields
в список своих элементов, а затем добавляет эти элементы в массив - она не каким-то образом "добавляет массив" @fields
как единый объект, который я Предположим, что вы ожидали. Так как он продолжает проходить по линиям, он продолжает строить этот длинный массив со всеми данными в одном длинном плоском списке.
Вместо этого добавьте ссылку на массив @fields
while (my $line = <$fh>) {
chomp $line;
my @fields = split /\s*,\s*/, $line;
push @data, \@fields;
}
, где Я также сократил пробелы, как только мы на это. (CSV вообще не должен иметь их.)
Здесь мы можем просто взять ссылку @fields
, потому что она объявляется заново для каждой итерации. Если бы оно было объявлено в другом месте и просто перезаписывалось в каждой итерации, вам нужно было бы скопировать его (в анонимный массив) вместо
while (my $line = <$fh>) {
chomp $line;
@fields = split /\s*,\s*/, $line; # if @fields is declared outside
push @data, [ @fields ];
}
, иначе вы бы получили одну и ту же ссылку для всех элементов @data
.
Теперь элементы @data
являются ссылками на строки и могут обрабатываться индивидуально. Например,
use List::Util qw(max);
my $max_name_wt = max map { length $_->[0] } @data;
printf "%${max_name_wt}s %6s %6s %6s\n", @{ shift @data }; # headers
foreach my $row (@data) {
printf "%${max_name_wt}s %6d %6d %6d\n", @$row;
}
Предполагается, что все числа целые и содержат не более 6 цифр. Также предполагается, что поля не пропущены, или их undef
будет выдавать предупреждения в printf
. List :: Util является основным модулем.
Существуют более простые способы печати сложных структур данных; см ядро Данные :: Дампер .