2009-04-14 30 views
29

Tôi biết tôi có thể liệt kê tất cả các gói và các biến lexcial trong một phạm vi nhất định sử dụng Padwalker 's peek_ourpeek_my, nhưng làm thế nào tôi có thể nhận được tên và giá trị của tất cả các biến toàn cầu như $"$/?Tôi làm cách nào để liệt kê tất cả các biến nằm trong một phạm vi nhất định?

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

Trả lời

27

Bạn có thể truy cập bảng biểu tượng, xem p. 293 của "Lập trình Perl" Ngoài ra nhìn vào "Mastering Perl: http://www252.pair.com/comdog/mastering_perl/ Cụ thể: http://www252.pair.com/comdog/mastering_perl/Chapters/08.symbol_tables.html

Những biến bạn đang tìm kiếm sẽ dưới namespace chính

Một tìm kiếm Google nhanh chóng đưa cho tôi:

{ 
    no strict 'refs'; 

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

Bạn cũng có thể làm

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

và tương tự cho giá trị khác

Nếu bạn muốn tìm những loại biểu tượng bạn có thể làm (từ thạo 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

% chính :: giữ các biến gói như "$ foo" của chúng tôi, chứ không phải biến toàn cầu như $ /. –

+0

Tôi lấy lại nó, tôi chỉ không nhận ra chúng bởi vì chúng đang thiếu mất dấu của chúng. Hmm, làm thế nào để tìm ra nếu họ là mảng, băm, hoặc vô hướng. –

+0

bạn có thể sử dụng chức năng 'ref' được tích hợp sẵn để có được loại biểu tượng. – fido

4

Bạn có thể làm một cái gì đó như sau để kiểm tra bảng biểu tượng của gói chính:

{ 
    no scrict 'refs'; 

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

oops, mất quá nhiều thời gian để đăng và MGoDave nhận được trước tôi với câu trả lời. Nhưng hãy chắc chắn bao gồm không có 'refs' nghiêm ngặt nếu bạn đang sử dụng nghiêm ngặt hoặc bạn sẽ nhận được một lỗi. – kbosak

+0

Trên thực tế, hóa ra đó chỉ là cách tôi mã hóa của tôi .. bạn có thể làm điều đó một cách nghiêm ngặt cách mã của bạn (ví dụ: khóa% chính :: không có dấu ngoặc kép) – kbosak

+0

Bạn có thực sự thử điều đó không? % main :: không chứa các biến toàn cục, chỉ các biến gói được khai báo trong gói chính. Tôi đang tìm các biến toàn cục như $ /. –

6

Và thực hiện điều đó. Nhờ MGoDave và kbosak để cung cấp câu trả lời trước mặt tôi rằng tôi đã quá ngu ngốc để xem (tôi đã xem% main :: để bắt đầu, nhưng bỏ lỡ rằng họ không có sigils của họ). Đây là mã hoàn chỉnh:

#!/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, đôi khi một cú đẩy đúng hướng là tất cả những gì cần thiết. – fido

+0

Tôi nhận được "Không thể ép buộc GLOB thành chuỗi trong enterub" ... được chữa khỏi bởi đề xuất này: [https://apg.at.ufl.edu/wiki/Can't%20coerce%20GLOB%20to%20string % 20in% 20entersub]. – Marcus

1

Cảm ơn, Chas, mã rất hữu ích. Lưu ý cho người dùng tương lai mã của bạn với perl> 5.12:

Tôi đã sử dụng nó trong pdl2 .perldlrc để tìm các biến từ vựng (như lệnh 'y' trong trình gỡ rối) và tôi đã cảnh báo :

load_rcfile: tải

/homes/pmg/.perldlrc định nghĩa (% hash) bị phản đối tại (eval 254) dòng 36.

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

Từ perldoc -f được xác định

Sử dụng định nghĩa trên tổng hợp (băm và mảng) không được dùng nữa. Nó được sử dụng để báo cáo liệu bộ nhớ cho rằng tổng hợp đã từng được phân bổ chưa. Hành vi này có thể biến mất trong tương lai phiên bản của Perl. Bạn nên thay vì sử dụng một thử nghiệm đơn giản cho kích thước:

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

Những gì tôi không hiểu là tại sao nó chỉ phàn nàn với băm xác định và không còn với mảng?

+2

Có mã chắc chắn để in một cảnh báo tương tự cho mảng (xem xung quanh dòng 7813 của op.c), nhưng 'perl -we '@a = được định nghĩa @ a'' dường như không kích hoạt nó, nhưng' perl-we '% h = (1, được xác định% h)' 'chắc chắn không kích hoạt cảnh báo. Điều này có mùi giống như một lỗi của một số hình thức. –

+2

Thú vị, bạn có thể kích hoạt cảnh báo với 'perl -wE' này của tôi @a; được định nghĩa @a? @a: "f" '', nhưng không phải« perl -wE »của chúng tôi @a; được định nghĩa @a? @a: "f" ''. Điều này dường như chỉ nói rằng các biến từ vựng thực tế sẽ ném cảnh báo. –

Các vấn đề liên quan