Ошибка устранения неполадок справки Perl MSG с использованием модуля Perl - PullRequest
0 голосов
/ 18 августа 2011

Я тестирую Perl-скрипт, используя пример , найденный на форуме. Я взял пример данных и поместил их в отдельный файл, используя пробную версию, чтобы попробовать это таким образом.

Я не понимаю, почему я получаю undef. Я получаю сообщение:

Использование неинициализированного значения в соединении или строке в ./h.pl, строка 15, строка 4.

#!/usr/local/bin/perl

use warnings;
use strict;
use Data::Dumper;
use Text::CSV_XS;

    open my $fh, '<', 't.out' or die "Unable to open: $!";
    my $csv = Text::CSV_XS->new( { sep_char => "\t" } );
    my @list;
    $csv->column_names ($csv->getline ($fh));
    while ( my $hr = $csv->getline_hr($fh) ) {
        push @list, $hr->{'Ball'};
    }

    print "@list\n";
    print Dumper(\@list);

Тестовый файл (t.out)

Camera Make Camera Model    Text    Ball    Swing
a   b   c   d   e
f   g   h   i   j
k   l   m   n   o


$ od -cx t.out 
0000000   C   a   m   e   r   a       M   a   k   e  \t   C   a   m   e
        6143 656d 6172 4d20 6b61 0965 6143 656d
0000020   r   a       M   o   d   e   l  \t   T   e   x   t  \t   B   a
        6172 4d20 646f 6c65 5409 7865 0974 6142
0000040   l   l  \t   S   w   i   n   g  \n   a  \t   b  \t   c  \t   d
        6c6c 5309 6977 676e 610a 6209 6309 6409
0000060  \t   e  \n   f  \t   g  \t   h  \t   i  \t   j  \n   k  \t   l
        6509 660a 6709 6809 6909 6a09 6b0a 6c09
0000100  \t   m  \t   n  \t   o  \n  \0
        6d09 6e09 6f09 000a
0000107

Результаты:

$VAR1 = [
          undef,
          undef,
          undef
        ];

Ответы [ 4 ]

2 голосов
/ 18 августа 2011

Если $csv->getline_hr($fh) возвращает неопределенное значение, вы получите предупреждение "Use of uninitialized value in join or string at ...", если попытаетесь напечатать список @list.

Вы можете проверить это явно с помощью простой программы:

use strict;
use warnings;
my @list;
my $x = undef; # This is similar to what may happen in your program on the `push @list, @hr->{'Name'}` line
push @list, $x;
print "@list\n";

Кроме того, вы можете вместо этого use Data::Dumper, а затем print Dumper(\@list), если вы просто выполняете отладку, поскольку вы не получите никаких предупреждений и получите более четкую картину того, что хранится в вашей структуре данных.

1 голос
/ 18 августа 2011

В вопросе, на который вы ссылаетесь, я также написал это в последней строке:

ETA: Если вы собираетесь вырезать и вставить, чтобы попробовать, убедитесь, что вкладкиперенесены в данные.

Удостоверились ли вы, что ваши вкладки пережили копирование / вставку в ваш файл 't.out'?

Этот модуль довольно не прощает плохих форматов вфайл данных.

Обновление:

Имейте в виду, что такое поле, как 'Ball ', будет считаться отличным от 'Ball'.Т.е. если у вас есть дополнительный пробел, он все испортит.

То, что вы можете попытаться исправить, это добавление allow_whitespace => 1, к опциям объекта $csv.Это исправит любые незначительные ошибки пробела во входном файле.

Вы также можете проверить ошибки форматирования, напечатав ключи заголовка с помощью

print Dumper $csv->column_names(); 
1 голос
/ 18 августа 2011

Как уже упоминали другие, вполне возможно, что @list никогда не получит значение в нем. Если $csv->getline_hr($fh) вернет undef в первый раз, вы никогда не вставите ничего в @list.

Есть две вещи, которые вы можете сделать:

  1. Вы можете проверить, не инициализирована ли @list перед печатью
  2. Вы можете ослабить прагму use warnings, чтобы не включать неинициализированные предупреждения:

Вот как вы можете провести тестирование:

if (@list) {
   print "List = " . @list . "\n";
} 
else {
   print "List has no values\n";
}

Вы можете использовать scalar @list, как показывает Игорь Зиновьев , но в данном случае это не является необходимым, и я думаю, что простое if (@list) более понятно. Вы также можете использовать if (defined @list), что очень понятно, но в последние несколько лет не поощряется.

Если это временная вещь (просто посмотрите, работает ваш код или нет), вы можете ослабить использование строгого:

no warnings qw(uninitialized);
print "@list\n";   #Now you won't get a warning if @list has no value
use warnings;      #Turn the warnings back on. It helps you code better

Небольшое слово: o Предупреждение: в этом случае ваше заявление ничего не напечатает, и это может еще больше сбить вас с толку. Всегда ставьте подсказку , чтобы убедиться, что что-то печатается:

print "\@list = @list\n";

Я предпочитаю это как временное решение , когда я печатаю много отладочных операторов, которые я позже удалю. Фактически, я создам специальную подпрограмму debug для этих типов сообщений:

use strict;
use warnings;
use constant DEBUG_LEVEL => 1;  #0 = no debug messages 1 = debug messages

[...]
while (yadda, yadda, yadda) {
   push @list, $hr->{Name};
}
debug (qq(\@list = ") . join "|", @list . qq("));

[...]

sub debug {
   my $message = shift;

   return if (not DEBUG_LEVEL);
   no warnings qw(uninitialized);
   print qq(DEBUG: $message\n);
   use warnings;      #Not really needed since the code block ends
   return $message;
}
0 голосов
/ 18 августа 2011

Кажется, ваш массив @list не определен.Попробуйте проверить это:

if (scalar @list) {
    print "@list\n";
}

Если ваш цикл while никогда не выполнялся, scalar @list вернет 0, поскольку массив пуст.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...