Pertanyaan Capture variabel tugas dalam suatu Perl eval


Saya ingin dapat menangkap tugas variabel dari Perl eval. Yaitu, untuk menentukan nama variabel apa yang telah ditetapkan dalam kode dan mengekstrak nilainya.

Misalnya jika saya menjalankan:

eval '$foo=42; $bar=3.14;'

Hasil eval adalah 3,14 (nilai terakhir dievaluasi), tetapi saya juga ingin dapat menentukan nama "$ foo" dan "$ bar" dan nilai-nilai mereka (tanpa mengetahui nama-nama sebelumnya).

Saya telah membaca tentang beberapa cara memasukkan variabel ke dalam blok eval, melalui Safe and Eval :: Context, tetapi belum cara mengekstraksinya. Saya lebih akrab dengan eval / exec Python yang telah membangun dukungan untuk ini.


5
2017-11-23 23:28


asal


Jawaban:


Inilah usaha saya untuk menyempurnakan solusi berdasarkan Aman, seperti yang disarankan oleh Eric Strom.

package main;
use warnings; use strict;
use Safe;

my $cpt = new Safe;

$cpt->permit_only(qw(sassign lineseq padany const rv2sv leaveeval));
my $name_space = $cpt->root;

my $no_strict = 0;
#
# populate the clean symbol table
#
$cpt->reval('0');
die "safe compartment initialisation error: $@" if $@;
my %symtab_clean = do {no strict 'refs'; %{$name_space.'::'} }; 

my $result = $cpt->reval('$foo=42; $bar=3.14;', $no_strict);

if ($@) {
    warn "eval error: $@";
}
else {
    #
    # symbol table additions
    #
    my %symtab_dirty = do {no strict 'refs'; %{$name_space.'::'} }; 

    my @updated_variables = grep { ! exists $symtab_clean{$_} } (sort keys %symtab_dirty);

    foreach my $variable (@updated_variables) {
        my $value = do{ no strict 'refs'; ${$name_space.'::'.$variable} };
       print "variable $variable was set to: $value\n"
    }
}

Catatan:

  1. Di atas memungkinkan satu set pembatasan minimal dari opcode aman. Lihat opc perl
  2. Saya telah memilih untuk mencari perbedaan sebelum dan sesudah mengeksekusi perintah

1
2017-11-24 01:45



Setiap variabel leksikal yang dinyatakan dalam suatu eval akan hilang setelah eval berakhir. Untuk menangkap dan mengisolasi variabel global yang diatur dalam suatu eval, Anda dapat melihat ke dalam menggunakan Aman modul untuk membuat namespace global baru. Sesuatu seperti yang berikut:

use Safe;

my $vars = Safe->new->reval(qq{
    $code_to_eval; 
    $code_to_search_the_symbol_table_for_declared_variables
});

Di mana kode pencarian didefinisikan sebagai sesuatu yang berjalan bersarang %main:: tabel simbol mencari setiap variabel yang menarik. Anda dapat memilikinya mengembalikan struktur data yang berisi informasi, dan kemudian Anda dapat melakukannya dengan apa yang Anda suka.

Jika Anda hanya mengkhawatirkan variabel yang ditentukan di tingkat akar, Anda dapat menulis sesuatu seperti:

use strict;
use warnings;

my $eval_code = '$foo=42; $bar=3.14;';

use Safe;
my $vars = Safe->new->reval(
    $eval_code . q{;
    my %vars;
    for my $name (keys %main::) {
        next if $name =~ /::$/    # exclude packages
         or not $name =~ /[a-z]/; # and names without lc letters

        my $glob = $main::{$name};
        for (qw($SCALAR @ARRAY %HASH)) {
            my ($sigil, $type) = /(.)(.+)/;
            if (my $ref = *$glob{$type}) {
                $vars{$sigil.$name} = /\$/ ? $$ref : $ref
            }
        }
    }
    \%vars
});

print "$_: $$vars{$_}\n" for keys %$vars;
# $foo: 42
# $bar: 3.14

Kode pencarian juga bisa menggunakan Padwalker untuk mencari lingkup leksikal saat ini untuk setiap variabel yang ditetapkan menggunakan peek_my fungsi.


7
2017-11-24 01:06



Nah, nilai $ foo akan menjadi 42 setelah eval dijalankan. Tidak ada perubahan dalam lingkup yang menjadikan $ foo tidak terlihat.

Tapi itu tentu saja menganggap sudah mengetahui keberadaan $ foo.

Bagaimanapun, ini hanya akan bekerja tanpa use strict set, yang hampir pasti ide yang buruk. Dengan use strict di tempat, skrip tidak dapat dikompilasi. Saya menganggap contoh Anda lebih kompleks, dan Anda mencari perubahan pada hash yang dilakukan oleh Anda eval. Tetapi tidak jelas bagaimana Anda eval tidak bisa tahu apa yang berubah, kecuali ada semacam injeksi kode dinamis yang terjadi.


0
2017-11-23 23:50