2009-04-09 12 views
9

Je cherche le meilleur, meilleure façon de faire quelque chose comme:Quelle est la meilleure façon de découvrir toutes les variables actuellement définies par une application Perl?

$var1="value"; 
bunch of code..... 
**print allVariablesAndTheirValuesCurrentlyDefined;** 
+0

Je pense que Data :: Dumper pourrait être capable de faire cela, mais je ne sais pas comment. –

+0

brian dit la vérité. La meilleure réponse est "ne pas" suivi de "pourquoi avez-vous voulu faire cela?" – Schwern

+0

brian/Schwern, on dirait qu'il y a une nouvelle question là-bas, "meta programmation rights and wrongs". Pouvez-vous me montrer des questions ou des liens sur quand et pourquoi la «réflexion» comme celle-ci est-elle une mauvaise idée? Fondamentalement, je voudrais juste envelopper un perl existant avec un nouveau perl avec aucun changement à l'application existante –

Répondre

9

Variables d'ensemble? Variables lexicales?

Les variables de package peuvent être consultées via la table de symboles. Essayez Devel::Symdump:

#!/path/to/perl 

use Devel::Symdump; 

package example; 

$var = "value"; 
@var = ("value1", "value2"); 
%var = ("key1" => "value1", "key2" => "value2"); 

my $obj = Devel::Symdump->new('example'); 

print $obj->as_string(); 

Les variables lexicales sont un peu Tricker, vous ne les trouverez pas dans le tableau des symboles. Ils peuvent être consultés via le « scratchpad » qui appartient au bloc de code elles sont définies dans PadWalker Essayez.

#!/path/to/perl 

use strict; 
use warnings; 

use Data::Dumper; 
use PadWalker qw(peek_my); 

my $var = "value"; 
my @var = ("value1", "value2"); 
my %var = ("key1" => "value1", "key2" => "value2"); 

my $hash_ref = peek_my(0); 

print Dumper($hash_ref); 
7

Le tableau symbole global est %main::, de sorte que vous pouvez obtenir des variables globales à partir de là. Cependant, chaque entrée est un typeglob qui peut contenir plusieurs valeurs, par exemple $ x, @x,% x, etc., vous devez donc vérifier chaque type de données. Vous pouvez trouver le code qui fait cela here. Les commentaires sur cette page peuvent vous aider à trouver d'autres solutions pour les variables non globales (comme les variables lexicales déclarées avec "my").

+0

Et n'oubliez pas de tous les autres paquets qui ont des variables dans la portée aussi! –

+0

+1, mais veuillez aussi mentionner que les variables lexicales (celles déclarées comme "my $ x;") ne sont pas listées dans% main :: ou ailleurs. :( –

+0

+1, mais il n'y a aucun moyen de garantir que le lien que vous fournissez fonctionnera toujours.Même si les perlmonks restent éternels, le site pourrait être réorganisé.Il pourrait être utile de mettre quelques informations sur l'utilisation de '% main ::' dans votre réponse. –

1

Nathan's answer fait partie de l'histoire - malheureusement, le reste de l'histoire est que les variables lexicales ne sont pas listées dans %main:: ou ailleurs (au moins accessible de Perl - il est probablement possible qui extrait cette information des internes de niveau C de Perl).

Les variables lexicales sont ce que vous utiliseriez normalement pour les variables "ordinaires locales". Ils sont déclarés comme:

my $x; 
+0

Heureusement, quelqu'un a déjà écrit le code XS poilu pour nous. Voir PadWalker sur CPAN. –

+0

@Chas: Intéressant. Bien que je me sentirais sale en utilisant PadWalker;) –

+0

En code de production? jamais. En code de développement, pas de problème. Pensez-y comme un débogueur programmable, en fait, je crois qu'il est utilisé par Devel :: ebug pour fournir les variables de surveillance. –

6

Le module PadWalker vous donne peek_my et peek_our qui prennent un argument de niveau qui détermine la portée à rechercher des variables:

The LEVEL argument is interpreted just like the argument to caller. 
So peek_my(0) returns a reference to a hash of all the my variables 
that are currently in scope; peek_my(1) returns a reference to a hash 
of all the my variables that are in scope at the point where the 
current sub was called, and so on. 

Voici un exemple:

#!/usr/bin/perl 

use strict; 
use warnings; 

use PadWalker qw/peek_my/; 

my $baz = "hi"; 

foo(); 

sub foo { 
    my $foo = 5; 
    my $bar = 10; 

    print "I have access to these variables\n"; 
    my $pad = peek_my(0); 
    for my $var (keys %$pad) { 
     print "\t$var\n"; 
    } 

    print "and the caller has these variables\n"; 
    $pad = peek_my(1); 
    for my $var (keys %$pad) { 
     print "\t$var\n"; 
    } 
} 
1

Serait-ce pour rien d'autre que des fins de débogage? Si non, vous pouvez vous familiariser avec perl's debugger. Une fois dans le débogueur, vous pouvez inspecter toutes les variables en émettant 'V'.

+0

non, pas tellement pour le débogage, cela ferait partie du chargement de l'exécution "dynamique" et ensuite de comprendre ce qui s'est chargé –

Questions connexes