2009-04-14 16 views
29

Sé que puedo enumerar todas las variables paquete y lexcial en un ámbito determinado usando Padwalker 's peek_our y peek_my, pero ¿cómo puedo obtener los nombres y valores de todas las variables globales como $" y $/?¿Cómo puedo enumerar todas las variables que están en un ámbito determinado?

#!/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); 
    #lexicals hide package variables 
    while (my ($var, $ref) = each %$lexical) { 
     $in_scope{$var} = $ref; 
    } 
    ############################################## 
    #FIXME: need to add globals to %in_scope here# 
    ############################################## 
    return \%in_scope; 
} 

Respuesta

27

Se puede acceder a la tabla de símbolos, echa un vistazo a p. 293 de "programación Perl" También se fijan en "Mastering Perl: http://www252.pair.com/comdog/mastering_perl/ Específicamente: http://www252.pair.com/comdog/mastering_perl/Chapters/08.symbol_tables.html

Aquellas variables que busca estarán bajo el espacio de nombres principal

Una rápida búsqueda en Google me dio:

{ 
    no strict 'refs'; 

    foreach my $entry (keys %main::) 
    { 
     print "$entry\n"; 
    } 
} 

también se puede hacer

*sym = $main::{"/"} 

y lo mismo para otros valores

Si desea encontrar el tipo de símbolo que puede hacer (de dominar 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}; 
} 
+0

% main :: contiene variables de paquete como "our $ foo", no variables globales como $ /. –

+0

Lo llevo de vuelta, simplemente no los reconocí porque faltan sus sellos. Hmm, cómo averiguar si son matrices, hashes o escalares. –

+0

puede usar la función incorporada 'ref' para obtener el tipo de símbolo. – fido

4

Usted puede hacer algo como lo siguiente para comprobar la tabla de símbolos del paquete principal:

{ 
    no scrict 'refs'; 

    for my $var (keys %{'main::'}) { 
     print "$var\n"; 
    } 
} 
+0

oops, tomó demasiado tiempo para publicar y MGoDave entró antes que yo con la respuesta. Pero asegúrese de no incluir scrict 'refs' si está usando strict o si no obtendrá un error. – kbosak

+0

En realidad, resulta que fue la forma en que codifiqué la mía ... puedes hacerlo con estricta forma en que tu código es (es decir, claves% main :: sin comillas) – kbosak

+0

¿De verdad lo intentaste? % main :: no contiene variables globales, solo variables de paquetes declaradas en el paquete principal. Estoy buscando las variables globales como $ /. –

6

Y eso lo hace. Gracias a MGoDave y a kbosak por darme la respuesta frente a mi cara que era demasiado estúpida para ver (busqué en% main :: para empezar, pero me perdí de que no tuvieran sus sellos). Aquí está el código completo:

#!/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; 
} 
+0

np, a veces un empujón en la dirección correcta es todo lo que se necesita. – fido

+0

Obtuve "No se puede forzar GLOB a la cadena en insub" ... que se curó con esta sugerencia: [https://apg.at.ufl.edu/wiki/Can't%20coerce%20GLOB%20to%20string % 20in% 20entersub]. – Marcus

1

Gracias, Chas, código muy útil. Como nota para futuros usuarios de su código con perl> 5.12:

Lo estaba usando en mi pdl2 .perldlrc para encontrar variables léxicas (como el comando 'y' en el depurador) y tuve esta advertencia :

load_rcfile: carga

/homes/pmg/.perldlrc definido (% hash) está en desuso al (254 eval) línea 36.

(Maybe you should just omit the defined()?) 

Desde perldoc -f definido

El uso de agregados definidos en (hashes y arrays) está en desuso. Solía ​​ informar si alguna vez se había asignado la memoria para ese agregado . Este comportamiento puede desaparecer en futuras versiones de Perl. En su lugar debe usar una prueba sencilla para el tamaño:

>  if (@an_array) { print "has array elements\n" } 
>  if (%a_hash) { print "has hash members\n" } 

Lo que no entiendo es por lo que sólo se quejó con el hash definido y no también con la matriz?

+2

Definitivamente hay un código para imprimir una advertencia similar para las matrices (ver alrededor de la línea 7813 de op.c), pero 'perl -we '@a = defined @ a'' no parece desencadenarlo, pero' perl -we '% h = (1, definido% h)' 'definitivamente dispara una advertencia. Esto huele a un error de alguna forma. –

+2

Interesante, puede desencadenar la advertencia con este 'perl -wE 'mi @a; decir definido @a? @a: "f" '', pero no este 'perl -wE' nuestro @a; ¿define @a? @a: "f" ''. Esto parece decir que solo las variables léxicas reales arrojarán la advertencia. –

Cuestiones relacionadas