Search code examples
perldebuggingscriptingpackagedereference

Perl: How to print variables and values from @EXPORT


I'm trying to create a log that lists all the perlvar I have exported from my package, for debug purposes. I'm having trouble getting the de-referencing from the @EXPORT to work.

I have a package that looks like something like this:

package my_lib;
use strict;
no strict 'refs';
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
our @ISA qw(Exporter);
our @EXPORT = qw();
use Exporter;

our $var1 = 1;
our $var2 = 5;
our $var3 = $var1 + $var2;
our @vars = [$var1, $var2];

my @my_exported = qw(
    $var1
    $var2
    $var3
    @vars
    );

sub dump_vars {
    foreach my $entry (@my_exported) {
#        my $value =~ s/(\$\w+)/$1/eeg;
        my $value =~ s/\$(\w+)/${$1}/g;
        print "$entry = $value\n";
    }
}

push(@EXPORT, @my_exported);
push(@EXPORT_OK, qw(&dump_vars));

1;
  • I've tried both versions for dereferencing $value, but it results in an empty string each time

Then I have perl script to generates a log that contains all the values in the package:

#!/usr/bin/perl

use my_lib qw(dump_vars);

#dump_vars();
eval dump_vars();
  • I tried both versions of calling the subroutine

I use this script like this:

gen_vars_lib_log.pl > vars_lib.log

I'm expecting the log to look something like this:

$var1 = 1
$var2 = 5
$var3 = 6
@vars = [1, 5]

But instead, I get this:

$var1 = 
$var2 = 
$var3 = 
@vars = 

Can someone help me see what I'm missing? I've read a bunch of pages on evaluating variables embedded in strings, but I can't get this to work.


Solution

  • The substitution operator is used as follows:

    $var_to_modify =~ s/.../.../
    

    So the following tries the modify the value of newly-created variable $value.

    my $value =~ s/\$(\w+)/${$1}/g;
    

    Always use use strict; use warnings;!! It would have caught that error.

    (Yeah, I realize you need use no strict 'refs'; here, though you should limit its scope to the portions of the code where its needed.)


    The second issue is that you even try to handle arrays. But before you could even try to do that, you would have to realize that the following creates an array with a single element:

    @vars = [ $var1, $var2 ];   # Assign 1 scalar, a reference to an array to @vars
    

    Presumable you wanted

    @vars = ( $var1, $var2 );   # Assign 2 scalars to @vars
    

    I'm going to use Data::Dumper to dump the values.


    package my_lib;
    
    use strict;
    use warnings;
    
    use Data::Dumper qw( Dumper );
    use Exporter     qw( import );
    
    our $var1 = 1;
    our $var2 = 5;
    our $var3 = $var1 + $var2;
    our @vars = ( $var1, $var2 );
    
    our @EXPORT = qw(
        $var1
        $var2
        $var3
        @vars
    );
    
    our @EXPORT_OK = qw( dump_vars );
    
    sub dump_vars {
        no strict qw( refs );
        local $Data::Dumper::Indent = 0;
        local $Data::Dumper::Terse  = 1;
        for my $entry (@EXPORT) {
            my $value;
            if ($entry =~ /^\$(\w+)\z/) {
               $value = Dumper(${ \$$1 });
            }
            elsif ($entry =~ /^\@(\w+)\z/) {
               $value = Dumper(\@$1);
               $value =~ s/^\[/(/;
               $value =~ s/\]\z/)/;               
            }
            elsif ($entry =~ /^\%(\w+)\z/) {
               $value = Dumper(\%$1);
               $value =~ s/^\{/(/;
               $value =~ s/\}\z/)/;               
            }
            else {
               next;
            }
    
            print "$entry = $value\n";
        }
    }
    
    1;
    

    Output:

    $ perl -I. -e'use my_lib qw( dump_vars ); dump_vars()'
    $var1 = 1
    $var2 = 5
    $var3 = 6
    @vars = (1,5)