2017-11-29 4 views
4

今日はとてもばかげているようですが、私は非常に奇妙な問題があります。次のコードを考えてみてください:undefのチェックにもかかわらず、uninitailized変数に関する警告

#!/usr/bin/perl 

use strict; 
use warnings; 
use warnings::unused; 
use warnings FATAL => 'uninitialized'; 

my ($String, $Pattern); 

$Pattern = "pattern"; 
$String = "pattern\n"; 

if (($String =~ m/^([^\ ]+).*$/s) && 
    defined($1) && 
    ($1 =~ m/^.*$Pattern$/s)) { 

    print $1."\n"; 
} 

このコードは次のように警告(その後、理由use warnings FATAL => 'uninitialized';の停止)生産:

Use of uninitialized value $1 in concatenation (.) or string at [...] 

私がテストしていので、$1が定義されている場合、私は本当にこのことを理解していません(初期化されています)。犯人が最後の条件行(すなわち、($1 =~ m/^.*$Pattern$/s))であるようです。私がこれを離れると、警告は消えてしまいます。

なぜですか?私の理解によると、その行はちょうどのテスト$1ですが、その値は変更されません($Pattern)。そのRegExの残りの部分にはカッコが含まれていないので、$1は一致する可能性があります。それについて考えながら

うーん、それは正規表現が一致したとき、Perlは正規表現で括弧があるかどうかに関係なく、すべてのケースを$1を設定し、でその同僚かもしれないことを私の心に来ます。これは行動を説明するでしょう。本当ですか?

+2

動作を示す簡単なテストケースを作成してみてください。私はこのコードに何か間違っているとは思わない。 – tinita

+0

これが起こることはわかっていました...私は実際のコードを削除しようとします。 – Binarus

+1

私は今質問をMCVEで更新しました。 – Binarus

答えて

8

:だから

if (($String =~ m/^([^\ ]+).*$/s) && # If matching, this will set $1 
    defined($1) &&     # Here $1 is still defined 
    ($1 =~ m/^.*$Pattern$/s)   # If matching, will reset all $1, .. vars 
) { 

、正規表現マッチは、それはすべての数字変数をリセットしますたびに(および他の正規表現関連する変数)。

私が見る唯一の解決策は、条件を分割して、余分な変数に$1を保存することです。とにかく普通は良いことです。

if ($String =~ m/^([^\ ]+).*$/s and defined $1) { 
    my $match = $1; 
    if ($match =~ m/^.*$Pattern$/s) { ... } 
} 

このパターンが一致した場合、$1は常に定義されますので、この場合には、あなたもdefined $1を確認する必要はありませんので注意してください。パターンによって異なります。

perldoc perlvar

$<digits> ($1, $2, ...) 
     Contains the subpattern from the corresponding set of capturing 
     parentheses from the last successful pattern match [...] 
9

perldoc perlvar

はすでに終了してきたネストされたブロックにマッチしたパターンを数えていない、最後に成功したパターンマッチから括弧を取り込むの対応するセットからのサブパターンが含まれています。

最後の成功したパターンマッチであるため、ifブロックの内側にある$1はundefです。

あなたが行うことができます:私は上記の私のコメントからの回答作成してい

my ($match) = ($String =~ m/^([^\ ]+).*$/s); 
if (defined $match && $match =~ m/^.*$Pattern$/s) { 
    print $match."\n"; 
} 
+0

ありがとう、upvoted。今は明らかです。 – Binarus

0

あなたは、複雑な文がやっているかわからない場合は、部分にそれを破ります。

if($String =~ m/^([^\ ]+).*$/s){ 
    if(defined($1)){ 
     if($1 =~ m/^.*$Pattern$/s){ 
関連する問題