3

コマンドライン引数からモジュール名と関数名を渡す必要があります。プログラムでコマンドライン引数を取得する必要があり、そのモジュールからその関数を呼び出す必要があります

たとえば、2 つの引数を指定して try.pl プログラムを呼び出す場合: MODULE1(モジュール名) Display(関数名)

 perl try.pl MODULE1 Display 

私はこのようなことをしたいのですが、うまくいきません。私を導いてください:

use $ARGV[0];
& $ARGV[0]::$ARGV[1]();
4

8 に答える 8

9

関数がクラスメソッドではないと仮定して、これを試してください:

#!/usr/bin/perl
use strict;
use warnings;

my ( $package, $function ) = @ARGV;

eval "use $package (); ${package}::$function()";
die $@ if $@;

この手法は、コード インジェクションに対して広く開かれていることに注意してください。(引数には、モジュール名の代わりに任意の Perl コードを簡単に含めることができます。)

于 2008-10-16T16:33:11.953 に答える
7

これを行うには多くの方法があります。それらの1つは次のとおりです。

#!/usr/bin/perl
use strict;
use warnings;

my ( $package, $function ) = @ARGV;

eval "use $package; 1" or die $@;

$package->$function();  

関数の最初の引数は $package になることに注意してください。

于 2008-10-16T16:17:35.170 に答える
4

モジュールが関数をエクスポートすると仮定すると、次のようになります。

perl -Mmodule -e function
于 2008-10-16T16:25:10.833 に答える
3

perl スクリプトが安全であることを確認したい場合 (または少なくとも、誤って愚かなことをしないようにしたい場合)、スクリプトに渡されたデータに対して、少なくとも何らかのチェックを行わずに、あらゆる種類の評価を行うことは避けます。しかし、とにかく何らかのチェックを行っていて、入力を明示的にチェックすることになった場合は、呼び出したいウィッチ メソッドを明示的に記述した方がよいでしょう。「既知の適切な」メソッドを使用してハッシュを設定できるため、呼び出し可能にするすべてのものを文書化し、同時に自分自身を保護できます。

my %routines = (
    Module => {
        Routine1 => \&Module::Method,
        Routine2 => \&Module::Method2, 
    },
    Module2 => { 
        # and so on
    },
);

my $module  = shift @ARGV;
my $routine = shift @ARGV;

if (defined $module
    && defined $routine
    && exists $routines{$module}            # use `exists` to prevent 
    && exists $routines{$module}{$routine}) # unnecessary autovivication
{
    $routines{$module}{$routine}->(@ARGV); # with remaining command line args
}
else { } # error handling

このメソッドの優れた副作用として、あらゆる種類のヘルプ出力に使用できるメソッドを単純に繰り返すことができます。

print "Available commands:\n";
foreach my $module (keys %routines)
{
    foreach my $routine (keys %$module)
    {
        print "$module::$routine\n";
    }
}  
于 2008-10-16T19:50:04.320 に答える
2

常に次のようにPerlを起動します。

use strict;
use warnings 'all';

次に、これを行います。

no strict 'refs';
my ($class, $method) = @_;
(my $file = "$class.pm") =~ s/::/\//g;
require $file;
&{"$class\::$method"}();

何をするにしても、「$string」を評価しないようにしてください。

于 2008-10-17T01:26:50.270 に答える
2

さて、修正された質問については、これを行うことができます:

use strict;
use warnings;

{
    no strict;
    use Symbol qw<qualify>;
    my $symb = qualify( $ARGV[1], $ARGV[0] );
    unless ( defined &{$symb} ) { 
        die "&$ARGV[1] not defined to package $ARGV[0]\::";
    }
    &{$symb};
}

また、コマンド ラインで指定しているため、コマンド ラインから含める最も簡単な方法は-Mフラグです。

perl -MMyModule try.pl MyModule a_subroutine_which_does_something_cool

しかし、いつでもできます

eval "use $ARGV[0];"; 

しかし、それはインジェクションの影響を非常に受けやすい:

perl try.pl "Carp; `do something disastrous`;" no_op
于 2008-10-17T02:45:59.160 に答える
2

Leon's によると、perl モジュールがそれをエクスポートしない場合は、次のように呼び出すことができます

perl -MMyModule -e 'MyModule::doit()'

サブがそのパッケージに含まれている場合。

常にサブをエクスポートする場合 (で@EXPORT)、Leon は機能します。

perl -MMyModule -e doit

オプションのエクスポート (の場合@EXPORT_OK) の場合は、次のように実行できます。

perl -MMyModule=doit -e doit

しかし、最初のものはサブがパッケージに定義されている場合はいつでも機能し、おそらく最後のものよりもそれを使用するでしょう.

于 2008-10-16T17:07:30.310 に答える
1

UNIVERSAL::requireを使用します。変数からモジュールを要求または使用できます。したがって、コードは次のように変更されます。

use UNIVERSAL::require;

$ARGV[0]->use or die $UNIVERSAL::require::ERROR;
$ARGV[0]::$ARGV[1]();

免責事項: 私はそのコードをテストしませんでした。コマンド ライン引数としてこれらを渡すよりも、おそらくより良い解決策があるという Robert P のコメントに同意します。

于 2008-10-21T01:20:56.257 に答える