1

末尾に " at File.pm line 123" が含まれる Perl 文字列例外を、どこかに出力して処理したい場合があります。ただし、パス名や行番号などで最後のビットを公開したくはありません。

時間の経過とともに、いくつかの可能な解決策を思いつきましたが、どれもあまり気に入りませんでした。このような正規表現を使用するだけでも明らかです。

s/\s+ at \s+ .*$//xms;

しかし、「 at 」という単語が含まれているものは何でも殺してしまうという問題があります。行番号をオプションでなくすると役立ちますが、「 at ANON 」または同様にグロテスクな何かが残る匿名コードになってしまいます。

私もこのようなことを試しました:

$_ = reverse $_;
s/^.*? \s+ ta \s+//xms;
$_ = reverse $_;

これは、1 行のエラーに対して非常にうまく機能します。confessただし、または他の例外スローワーからの完全なスタック トレースが発生した場合は、長いスタック トレースが配置されたままになります。

誰かが共有したい良い解決策を持っていますか? またはより良い方法に関する提案はありますか?(「そのようなダイメッセージを出力しないでください」は受け入れられる答えではありません。)

ここで見落としていた CPAN モジュールがある場合は、知りたいです。そうでない場合は、この目的のために CPAN モジュールを提供することを考えています。

4

3 に答える 3

4
  1. あなたの最初のスニペットは、「" at " という単語が入っているものは何でも殺す」わけではありません。at何かをするためには、最後から2番目の単語でなければなりません。

  2. あなたの 2 つのスニペット (前方と後方) は 100% 同等だと思います (ただし、2 番目のスニペットは末尾の改行をサポートしていないため、おそらく一致することはありません)。

  3. パターン

    /\s+ at \s+ \S+ (?:\s+ line \s+ \d+)?$/x
    

    一致しません

    $ perl -e'(eval "sub { die }")->()'
    Died at (eval 1) line 1.
    
  4. パターン

    /\s+ at \s+ \S+ (?:\s+ line \s+ \d+)?$/x
    

    一致しません

    $ echo foo | perl -e'<STDIN>; die;'
    Died at -e line 1, <STDIN> line 1.
    
  5. Perl が番号を追加せずにファイル名を追加することはないと思います。

    行番号がオプションの場合、「Dinner is at nine.」の最後の 2 つの単語と一致することは避けられません。ヒューリスティックを採用しない限り。


ソースコードを見ると、これがdie追加できるものです:

Adds:                   " at %s line %"IVdf
Sometimes followed by:  ", <%"SVf"> line %"IVdf
                or by:  ", <%"SVf"> chunk %"IVdf
Sometimes followed by:  " during global destruction"
Always followed by:     ".\n"

これにより、次のことがわかります。

s/
   (?&BASE)
   (?&IO_CLAUSE)?
   (?&GLOBAL_DESTR)?
   \.?\n\z

   (?(DEFINE)
      (?<BASE>         [ ] at [ ] (?&FILE_NAME) [ ] line [ ] [0-9]+ )
      (?<IO_CLAUSE>    , [ ] <(?&HANDLE_NAME)> [ ] (?:line|chunk) [ ] [0-9]+ )
      (?<GLOBAL_DESTR> [ ]during[ ]global[ ]destruction )

      # Heuristics:
      (?<FILE_NAME>   \S+ | \(eval[ ][0-9]+\) )
      (?<HANDLE_NAME> \w+ )
   )
//x

それは可能な限り具体的です。

(注:.私が聞いたところによると、Carp は末尾の " " を忘れることがあります。)

(注: Perl は単一のスペースを使用するため、[ ]より正確です\s+。)

于 2012-09-26T19:54:12.257 に答える
2

関数dieを定義することで、ビルトインをオーバーライドできます。CORE::GLOBAL::die

BEGIN {
    *CORE::GLOBAL::die = sub {
        my $y = pop @_;
        chomp $y;
        CORE::die @_,$y,"\n";
    }
}

my $method = rand(3);
die "I died\n" if $method > 2;
die "I died too" if $method > 1;
die;

次のいずれかを報告します

I died
I died too
<nothing - maybe not the right thing to do>

CORE::GLOBAL::...パッケージの使用方法は に記載されていperlsubます。

于 2012-09-26T20:56:28.117 に答える
0

標準die出力には常にパーツが含まれてatいると思いますlineので、以下を使用するだけで十分です。

s/\s+at\s(?!.*\bat\b).*\sline\s\d+\.$//;
于 2012-09-26T19:51:54.237 に答える