Nel caso completamente in generale, non si può fare ciò che vuoi grazie al seguente estratto da perlref:
*foo{THING}
restituisce undef
se quella COSA particolare non è stata ancora utilizzata, tranne nel caso di scalari. *foo{SCALAR}
restituisce un riferimento a uno scalare anonimo se $foo
non è stato ancora utilizzato. Questo potrebbe cambiare in una versione futura.
Ma se siete disposti ad accettare la restrizione che qualsiasi scalare deve avere un valore definito per essere rilevato, allora si potrebbe utilizzare il codice come
#! /usr/bin/perl
use strict;
use warnings;
open my $fh, "<", \$_; # get DynaLoader out of the way
my %before = %main::;
require "my.config";
my %after = %main::;
foreach my $name (sort keys %after) {
unless (exists $before{$name}) {
no strict 'refs';
my $glob = $after{$name};
print "\$$name\n" if defined ${ *{$glob}{SCALAR} };
print "\@$name\n" if defined *{$glob}{ARRAY};
print "%$name\n" if defined *{$glob}{HASH};
print "&$name\n" if defined *{$glob}{CODE};
print "$name (format)\n" if defined *{$glob}{FORMAT};
print "$name (filehandle)\n" if defined *{$glob}{IO};
}
}
si arriva lì.
Con my.config
di
$JACKPOT = 3_756_788;
$YOU_CANT_SEE_ME = undef;
@OPTIONS = qw/ apple cherries bar orange lemon /;
%CREDITS = (1 => 1, 5 => 6, 10 => 15);
sub is_jackpot {
local $" = ""; # " fix Stack Overflow highlighting
"@_[0,1,2]" eq "barbarbar";
}
open FH, "<", \$JACKPOT;
format WinMessage =
You win!
.
l'uscita è
%CREDITS
FH (filehandle)
$JACKPOT
@OPTIONS
WinMessage (format)
&is_jackpot
Stampa i nomi prende un po 'di lavoro, ma possiamo usare il modulo Data::Dumper
di prendere parte degli oneri. La questione anteriore è simile:
#! /usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub _dump {
my($ref) = @_;
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = 1;
scalar Dumper $ref;
}
open my $fh, "<", \$_; # get DynaLoader out of the way
my %before = %main::;
require "my.config";
my %after = %main::;
Abbiamo bisogno di eseguire il dump dei vari slot in modo leggermente diverso e in ogni caso rimuovere gli orpelli di riferimenti:
my %dump = (
SCALAR => sub {
my($ref,$name) = @_;
return unless defined $$ref;
"\$$name = " . substr _dump($ref), 1;
},
ARRAY => sub {
my($ref,$name) = @_;
return unless defined $ref;
for ("\@$name = " . _dump $ref) {
s/= \[/= (/;
s/\]$/)/;
return $_;
}
},
HASH => sub {
my($ref,$name) = @_;
return unless defined $ref;
for ("%$name = " . _dump $ref) {
s/= \{/= (/;
s/\}$/)/;
return $_;
}
},
);
Infine, un loop all'interno di set-differenza tra %before
e %after
:
foreach my $name (sort keys %after) {
unless (exists $before{$name}) {
no strict 'refs';
my $glob = $after{$name};
foreach my $slot (keys %dump) {
my $var = $dump{$slot}(*{$glob}{$slot},$name);
print $var, "\n" if defined $var;
}
}
}
Utilizzando la my.config
dalla tua domanda, l'uscita è
$ ./prog.pl
@A = ('a','b','c')
%B = ('b' => 'bee')
$C = 'see'
Lo snippet di codice corrente funziona per te? In caso contrario, hai un semplice file di configurazione di esempio che potresti pubblicare? –
@molecules Ho aggiunto un esempio di configurazione. È solo perl molto semplice. – bukzor
@molecules: Se ho capito bene, significa che otterrò sempre dei falsi positivi per gli scalari, ma poi potrò controllare se il valore è undef, e inoltre dovrei essere ancora in grado di rilevare ARRAY e HASH correttamente. – bukzor