I know I can list all of the package and lexcial variables in a given scope using Padwalker\'s peek_our
and peek_my
, but how can I get the names an
You can access the symbol table, check out p. 293 of "Programming Perl" Also look at "Mastering Perl: http://www252.pair.com/comdog/mastering_perl/ Specifically: http://www252.pair.com/comdog/mastering_perl/Chapters/08.symbol_tables.html
Those variables you are looking for will be under the main namespace
A quick Google search gave me:
{
no strict 'refs';
foreach my $entry ( keys %main:: )
{
print "$entry\n";
}
}
You can also do
*sym = $main::{"/"}
and likewise for other values
If you want to find the type of the symbol you can do (from mastering perl):
foreach my $entry ( keys %main:: )
{
print "-" x 30, "Name: $entry\n";
print "\tscalar is defined\n" if defined ${$entry};
print "\tarray is defined\n" if defined @{$entry};
print "\thash is defined\n" if defined %{$entry};
print "\tsub is defined\n" if defined &{$entry};
}
Thanks, Chas, very useful code. As a note for future users of your code with perl > 5.12:
I was using it in in my pdl2 .perldlrc to find out lexical variables (like the 'y' command in the debugger) and I had this warning:
load_rcfile: loading
/homes/pmg/.perldlrc defined(%hash) is deprecated at (eval 254) line 36.
(Maybe you should just omit the defined()?)
From perldoc -f defined
Use of defined on aggregates (hashes and arrays) is deprecated. It used to report whether memory for that aggregate had ever been allocated. This behavior may disappear in future versions of Perl. You should instead use a simple test for size:
> if (@an_array) { print "has array elements\n" }
> if (%a_hash) { print "has hash members\n" }
What I don't understand is why it only complained with the defined hash and not also with the array?
You can do something like the following to check the symbol table of the main package:
{
no strict 'refs';
for my $var (keys %{'main::'}) {
print "$var\n";
}
}
And that does it. Thanks to MGoDave and kbosak for providing the answer in front of my face that I was too stupid to see (I looked in %main:: to start with, but missed that they didn't have their sigils). Here is the complete code:
#!/usr/bin/perl
use strict;
use warnings;
use PadWalker qw/peek_our peek_my/;
use Data::Dumper;
our $foo = 1;
our $bar = 2;
{
my $foo = 3;
print Dumper in_scope_variables();
}
print Dumper in_scope_variables();
sub in_scope_variables {
my %in_scope = %{peek_our(1)};
my $lexical = peek_my(1);
for my $name (keys %main::) {
my $glob = $main::{$name};
if (defined ${$glob}) {
$in_scope{'$' . $name} = ${$glob};
}
if (defined @{$glob}) {
$in_scope{'@' . $name} = [@{$glob}];
}
if (defined %{$glob}) {
$in_scope{'%' . $name} = {%{$glob}};
}
}
#lexicals hide package variables
while (my ($var, $ref) = each %$lexical) {
$in_scope{$var} = $ref;
}
return \%in_scope;
}