1

Perl を使用して、外部の Perl スクリプトからすべてのグローバル変数をキャプチャするのが好きです。現在、私は型検出をぶらぶらしています。

正しいデータ型 (''、'SCALAR'、'HASH'、'ARRAY'、'CODE') を判別する方法は?

パーサー スクリプト:

my %allVariables = ();
{
     do "scriptToBeParsed.pl";
     foreach my $sym ( keys %main:: ) {
         # Get all normal variables and scalar/hash/array references:
        if ( ref( *{"$sym"} ) =~ m/^(?:|SCALAR|HASH|ARRAY)$/ ) {
            $allVariables{"$sym"} = *{"$sym"};
        }
    }
}

解析するスクリプト:

$someVariable1 = 'Yes, I like to be captured';
$otherVariable2 = \'And I also want to be captured';
%anotherVariable3 = ( 'Capture' => 'me' );
@lameVariable4 = ( 'Capture', 'me' );
$fooVariable5 = { 'Capture' => 'me' };
$barVariable6 = [ 'Capture', 'me' ];
$subVariable7 = sub { return "Don't capture me!" };
sub dontCaptureMe { return "Don't capture me!" }

私の例では、ref( *{"$sym"} )常に「GLOB」を返します(もちろん)。

4

2 に答える 2

3

もう 1 つのアプローチは、型グロブの has-like アクセスを使用することです。これについては、brian d foy のMastering Perlの131f ページの第 8 章で説明されています。

package test;
no strict;
no warnings; 

$someVariable1 = 'Yes, I like to be captured';
$otherVariable2 = \'And I also want to be captured';
%anotherVariable3 = ( 'Capture' => 'me' );
@lameVariable4 = ( 'Capture', 'me' );
$fooVariable5 = { 'Capture' => 'me' };
$barVariable6 = [ 'Capture', 'me' ];
$subVariable7 = sub { return "Don't capture me!" };
sub dontCaptureMe { return "Don't capture me!" }

say $dontCaptureMe;
my %allVariables = ();
{
  do "scriptToBecomeParsed.pl";
  foreach my $sym ( keys %test:: ) {
    for (qw( SCALAR HASH ARRAY CODE IO)) {
      if (*{"$sym"}{$_}) {
        $allVariables{$_}->{"$sym"} = *{"$sym"}{$_};
      }
    }
  }
}

print Data::Dumper::Dumper \%allVariables;

これにより、次の出力が生成されます。

$VAR1 = {
          'CODE' => {
                      'dontCaptureMe' => sub { "DUMMY" }
                    },
          'ARRAY' => {
                       'lameVariable4' => [
                                            'Capture',
                                            'me'
                                          ]
                     },
          'HASH' => {
                      'anotherVariable3' => {
                                              'Capture' => 'me'
                                            }
                    },
          'SCALAR' => {
                        'someVariable1' => \'Yes, I like to be captured',
                        '__ANON__' => \undef,
                        'subVariable7' => \sub { "DUMMY" },
                        'dontCaptureMe' => \undef,
                        'otherVariable2' => \\'And I also want to be captured',
                        'BEGIN' => \undef,
                        'barVariable6' => \[
                                              'Capture',
                                              'me'
                                            ],
                        'anotherVariable3' => \undef,
                        'lameVariable4' => \undef,
                        'fooVariable5' => \{
                                              'Capture' => 'me'
                                            }
                      }
        };
于 2012-08-06T15:05:30.080 に答える
1

あなたが言ったように

ref( *{"$sym"} ) は常に 'GLOB' を返します (もちろん)。

perl はシンボル テーブルのすべてをグロブに格納するため、何かがどのデータ型であるかを判別することは不可能です。これは、perl では配列、スカラー、ハッシュ、または同じ名前の他のものを持つことが完全に有効であるためです...このため、perl は衝突を避けるためにすべてをグロブに格納します。できることは、シンボル テーブル内のすべてのシンボルをループし、可能性のあるすべてのものに対して各グロブをテストし (セットが大きすぎない)、どのシンボルが設定されているかを確認することです。

$別の方法として、perl スクリプトをテキストとしてロードし、%@subopen(ファイルハンドル) を解析してすべてのタイプを確認するという、より実用的な方法があります。

于 2012-08-06T14:48:37.737 に答える