如何在Perl中跟踪全局变量?

dew*_*man 1 io perl file

我正在寻找别人的代码,他们打开一个文件:

(open (FILEHANDLE,'/homedirectory/textfile.txt')) 
Run Code Online (Sandbox Code Playgroud)

然后,他们将每行的内容放入一个变量进行处理(文件的每一行都包含由制表符分隔的数据):

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

然后他做了类似的事情:

$index = join('_', $var1, $var2, $var3);
Run Code Online (Sandbox Code Playgroud)

然后做这个(我划伤脑袋的部分)

$contents = $filehandle{"$index"};
Run Code Online (Sandbox Code Playgroud)

我尝试打印出来$contents,它看起来像是值$var1,$var2并且$var3全部用分号分隔(例如" value1;value2;value3").另外,我更改了FILEHANDLEto 的名称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"};
Run Code Online (Sandbox Code Playgroud)

要清楚,$filehandle在这个时刻第一次出现......也可能会注意到之前设置了类似名称的东西,但它是这样的:

abcd_filehandle{"$randomvar} = "VALUEX;VALUEY;VALUEZ";
Run Code Online (Sandbox Code Playgroud)

DVK*_*DVK 7

简短的回答:正如卡罗宁先生提到的那样,标识符filehandle(在您的情况下,考虑使用情况$filehandle{$key},标识符是一个哈希%filehandle)与裸字无关FILEHANDLE.它们碰巧被命名为相似(但完全不同,因为Perl区分大小写).

最有可能的是,哈希%filehandle- 由于它的值似乎实际上不是文件句柄而被命名为非常糟糕 - 在代码中的其他地方填充.要验证这一点,您需要做两件事:

  • grep在您的文件上运行命令,如下所示:grep filehandle your_file.pl

  • 通过以下方法启动方法,检查调用子例程时该哈希的内容是什么:

    sub myfn{
        use Data::Dumper; 
        print Data::Dumper->Dump([\%filehandle]);
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过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
Run Code Online (Sandbox Code Playgroud)