Как я могу отследить глобальную переменную в Perl? - PullRequest
1 голос
/ 05 ноября 2011

Я смотрю на чей-то другой код, и они открывают файл следующим образом:

(open (FILEHANDLE,'/homedirectory/textfile.txt')) 

затем они помещают содержимое каждой строки в переменную для обработки (каждая строка файла состоит из данных, разделенных табуляцией):

while(<FILEHANDLE>) {
($var1, $var2, $var3, $var4) = split (/\t+/, $_);

тогда он делает что-то вроде:

$index = join('_', $var1, $var2, $var3);

и затем делает ЭТО (часть, где я чешу голову)

$contents = $filehandle{"$index"};

Я попытался распечатать $contents, и выглядело, как будто это были значения $var1, $var2 и $var3, разделенные точкой с запятой (например, "value1;value2;value3"). Кроме того, я изменил имя FILEHANDLE на FILEHANDLE2 и сделал то же самое для $filehandle, и я получил точно такой же результат, так что это наводит меня на мысль, что они связаны. Кроме того, если оставить FILEHANDLE в покое и изменить $filehandle на $filehandle2, ничего не появится. Любая помощь будет принята с благодарностью, так как я застрял на этом довольно долгое время. Кроме того, я Perl N00B ... (я в основном программирую на Python).

По запросу, вот более полная версия кода:

sub myfn{
    $filename = "home/textfile.txt";
    open(FILEHANDLE, $filename) || die "Can't find filename\n";
    while (<FILEHANDLE>) {
        ($var1, $var2, $var3) = split (/\t+/, $_);
        $used_index = join ('_', $var1, $var2, $var3);  
        $tmp_index = uc ($used_index)
        $contents = $filehandle{"$tmp_index"};

, чтобы быть ясным, $filehandle появляется впервые на этом этапе ... также следует отметить, что что-то с похожим именем задано ранее, но это так:

abcd_filehandle{"$randomvar} = "VALUEX;VALUEY;VALUEZ";

Ответы [ 2 ]

7 голосов
/ 05 ноября 2011

Краткий ответ: как намекал г-н Каронен, идентификатор filehandle (в вашем случае, учитывая использование $filehandle{$key}, идентификатор - это хеш %filehandle) не имеет никакого отношения к голому слову FILEHANDLE.Просто им присваиваются одинаковые имена (но вовсе не идентично, поскольку Perl чувствителен к регистру).

Скорее всего, хэш %filehandle - кстати, очень плохо назван, поскольку его значения на самом деле не кажутсябыть файловыми дескрипторами - заполняется в другом месте кода.Чтобы убедиться в этом, вам нужно сделать 2 вещи:

  • выполнить команду grep в вашем файле следующим образом: grep filehandle your_file.pl

  • Проверьте, что представляет собой содержимое этого хеша при вызове подпрограммы, запустив ваш метод с:

    sub myfn{
        use Data::Dumper; 
        print Data::Dumper->Dump([\%filehandle]);
    
  • Посмотрите, где эта переменная изменяется в коде, запустив ваш скрипт черезОтладчик Perl (возьмите вашу текущую командную строку и предварительно ожидайте ее с perl -d).В отладчике установите выражение наблюдения, введя команду w %filehandle, а затем выполните сценарий с помощью c (продолжить)

Глядя на опубликованный код, кажется,написано в очень плохой форме с использованием глобальных переменных.Проблема, с которой вы столкнулись при ее понимании, является на 100% прекрасным примером того, почему использование глобальных переменных на любом языке является очень плохой идеей.Сравните это с кодом, который я написал бы для этой цели (при условии, что мои предположения верны относительно того, что такое% filehandle):

# Caller code
my %file_data = (1=>2); # What the original code called %filehandle hash
myfn(\%file_data); # Pass by reference

sub myfn {
    my($file_data) = @_; # A hashref, passed from caller code
    my $filename = "home/textfile.txt";
    open(my $filehandle, "<", $filename) || die "Can't find filename. Error: $!\n";
    while (<$filehandle>) {
        my ($var1, $var2, $var3) = split (/\t+/, $_);
        my $used_index = join ('_', $var1, $var2, $var3);  
        my $uc_index = uc($used_index);
        my $contents = $file_data->{$uc_index}; # Using -> to dereference hashref
0 голосов
/ 05 ноября 2011

См. perldoc perlopentut . Оба

open FILEHANDLE, '<', 'filename' or die $!;
while (<FILEHANDLE>) {
    # do something with $_
}
close FILEHANDLE;

и

open $filehandle, '<', 'filename' or die $!;
while (<$filehandle>) {
    # do something with $_
}
close $filehandle;

являются допустимыми способами открывать и читать файл, но голое слово FILEHANDLE и скалярная переменная $filehandle не имеют ничего общего друг с другом (если вы ранее не установили $filehandle = \*FILEHANDLE или что-то подобное). Вы даже можете сделать

open my $filehandle, '<', 'filename' or die $!;
while (<$filehandle>) {
    # do something with $_
}
# file is closed automatically when $filehandle goes out of scope

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

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