5

Perl のSafeモジュールのrevalを使用していますが、eval された文字列を解析できない場合に警告が生成されないようにしたいです (実際には、警告がまったく生成されないようにしたいのです)。

たとえば、次のコード:

use strict; use warnings;
use Safe;    
use feature qw/say/;
my $cft = Safe->new;

my $x = $cft->reval(') 1' );
my $y = $cft->reval('2'   );
say "x: $x";
say "y: $y";

結果:

Number found where operator expected at (eval 5) line 1, near ") 1"
    (Missing operator before 1?)
Use of uninitialized value $x in concatenation (.) or string at ./test line 12.
x: 
y: 2

私が達成しようとしているのは、$x = undef および $y = 2 で、警告がないことです。「警告なし」を入れてみました。新しいスコープ内ですが、reval 内から生成される警告には影響しません (ただし、@DavidO で指摘されているように、「初期化されていない値」の警告は無効になります):

use strict; use warnings;
use Safe;    
use feature qw/say/;
my $cft = Safe->new;
{
    no warnings;
    my $x = $cft->reval(') 1' );
    my $y = $cft->reval('2'   );
    say "x: $x";
    say "y: $y";
}

どういうわけか「警告なし」は Safe コンパートメント内にある必要があると思います。そのため、「警告なし」も先頭に追加しようとしました。評価される文字列に:

use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
{
    my $x = $cft->reval( 'no warnings;' . ') 1' );
    my $y = $cft->reval( 'no warnings;' . '2'   );
    say "x: $x";
    say "y: $y";
}

このように reval は警告を発行しませんが、両方の変数が未定義です:

Use of uninitialized value $x in concatenation (.) or string at ./test line 10.
x: 
Use of uninitialized value $y in concatenation (.) or string at ./test line 11.
y:

他に何を試すべきかわかりません。問題の説明が十分に明確であることを願っています。

4

2 に答える 2

4

確認すると、失敗した $@ことがわかります。. つまり、Safe はその役割を果たし、そのコードがライブラリをロードしようとするのを防ぎます。$cft->reval( 'no warnings;' . ') 1' );'require' trapped by operation mask at (eval 5) line 1.

$cft->reval( 'BEGIN { warnings->unimport; } ) 1' );警告がすでにコンパートメントの外にロードされていると仮定すると、うまくいきます。ただし、コンパイル時のエラーが発生することはありません。とは異なりevalrevalそれらを通過させるようです。STDERR を静かにする amon の手法を使用します。

于 2012-07-26T21:25:16.830 に答える
4

no warningsuse warningsプラグマが生成するすべての警告を抑制します。おそらく、尿も除去したいと思うでしょうstrict。ただし、重大な解析エラーがいずれにしても発生します。

STDERR への出力なしで、どんなに病的なコードでも実行したい場合は、ローカルでシグナル ハンドラを変更する必要があります。

{
  # I know what I'm doing!
  local $SIG{__WARN__} = sub {}; # locally ignore any warnings
  eval $code; # catches all "die"
}

STDERRまたは、再開することができ/dev/nullます:

{
  # I know what I'm doing!
  open my $oldSTDERR, '>&' \*STDERR or die;
  close STDERR or die;
  open STDERR, '>', '/dev/null' or die;

  eval $code;

  close STDERR or die;
  open STDERR, '>&', $oldSTDERR or die;
  close $oldSTDERR;
}
于 2012-07-26T20:46:58.130 に答える