2017-11-02 9 views
6

プログラム名が.tで終わるテストスクリプトの場合は、条件付きでパッケージをロードしたいと思います。REGEX_CONDの場合のバグ

しかし、条件が正規表現のときにuse ifが失敗するバグが発生しています。私はこれをPerl 5.10と5.16でテストしました。

$ ./test.t 
$0 is './test.t' 
List::Util is included 

ただし、拡張子.plと同じファイルには、失敗します:

#!/usr/bin/env perl 

use v5.10; 

BEGIN { say "\$0 is '$0'" } 

use if $0 =~ /\.t\z/, 'List::Util', ('pairmap'); 

say "List::Util is " . ($INC{"List/Util.pm"} ? '' : 'NOT ') . 'included'; 

出力:

は.Tで終わる私のテストスクリプトです

$ ./test.pl 
$0 is './test.pl' 
Can't locate pairmap.pm in @INC (@INC contains: /usr/lib64/perl5/5.10.0 /usr/lib64/perl5 /usr/local/share/perl5/x86_64-linux-thread-multi /usr/local/share/perl5 /usr/local/lib64/perl5 /usr/share/perl5 /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/share/perl5/if.pm line 13. 
BEGIN failed--compilation aborted at ./test.pl line 7. 

正規表現を二重にしたり、substrの比較に変更したりすると、コードを動作させることができます。

use if !!($0 =~ /\.t\z/), 'List::Util', ('pairmap'); 
use if substr($0, -2) eq '.t', 'List::Util', ('pairmap'); 

出力:

$ ./test.pl 
$0 is './test.pl' 
List::Util is NOT included 

これは既知のバグですか?もしそうなら、どんなバージョンで修正されましたか?

答えて

8

これはコードのバグです。

use MODULEの後の引数リストは、よく、リストコンテキストです。

m// in list context成功した場合はキャプチャされた文字列のリストを返します(正規表現にキャプチャグループが含まれていない場合は1)。失敗した場合は空のリストを返します。

したがって:リストコンテキストで

use if "test.pl" =~ /\.t\z/, 'List::Util', ('pairmap'); 

use if(), 'List::Util', ('pairmap'); 

と等価である(一致は非常に空のリストが返され、失敗)

,は、リスト連結演算子であり、だからこれは与える:

use if 'List::Util', 'pairmap'; 

'List::Util'が真値であるので、これは最終的にローディングpairmap.pmを終わる:

修正が一致スカラーコンテキストを与えることである
use pairmap; 

use if scalar($0 =~ /\.t\z/), 'List::Util', 'pairmap'; 

!、そのオペランドにスカラコンテキストを供給し、 !!と同じ効果があります)

関連する問題