2012-08-28 10 views
6

Otrzymuję ostrzeżenie z jednym z moich skryptów Perla. Błąd jest zgłaszany przy prostym oświadczeniu if, w którym testuję, czy łańcuch w tablicy jest równy innemu łańcuchowi znaków.Niezainicjowana wartość w ciągu "eq" Perl

Mój współpracownik i ja próbowaliśmy kilku scenariuszy i nadal nie byliśmy w stanie rozwiązać ostrzeżeń. Próbowałem umieścić wszystkie moje dotychczasowe badania w tym wątku, więc jest trochę za długi, ale proszę, trzymaj się go. Całkowicie utknąłem w nadziei, że jeden z wielkich umysłów Stack   Overflow może mi pomóc!

Kod generowania problemów jest:

if ($pieces[0] eq "PromotionNumber") 

Blok kodu wokół tej sekcji jest:

my @pieces = split(/=/, $var); 
if($pieces[0] eq "PromotionNumber") { 
    $promoNumber = $pieces[1]; 
} elsif ($pieces[0] eq "Type") { 
# More similar code follows 

Moim celem w powyższym kodzie jest przypisanie wszystkich zmiennych Znalazłem w pliku tekstowym do odpowiednich zmiennych Perla. Następnie wstawiam te znalezione zmienne do bazy danych SQL.

Plik tekstowy ma kilka pól, które mogą być w różnych zamówieniach, dlatego używam stylu przełącznika if-elsif ..., aby dokonać przypisania wartości. Są też pola, na których mi nie zależy, takie jak Level, i po prostu zignorowałem te pola. Te pola są jednak polami, które powodują ostrzeżenia.

$var jest ustawiony na następujące gdyż pętle przez ...

PromotionNumber=000 
RecordOffset=0 
Code=0 
SubCode=1 
Level=0 

Kiedy hit „Poziom = 0”, mogę wstrzymać w debuggera PerlIDE.exe i zobaczyć, że ciąg jest dzielony do poziomu i 0 i wstawione do tablicy. Jednak, gdy kod przejdzie do oświadczenia if i testów $pieces[0] eq "PromotionNumber" otrzymam ostrzeżenie.

Mogę nawet wydrukować $ pieces [0] tuż przed wyciągiem if, a wydrukuje on "Level".

Gdybym zmienić kod na następujące ostrzeżenie odchodzi ...

my @pieces = split(/=/, $var); 
if($pieces[0] eq "Level") { 
    #My problematic variable test 
}elsif($pieces[0] eq "PromotionNumber") { 
    $promoNumber = $pieces[1]; 
} elsif ($pieces[0] eq "Type") { 
#More similar code follows 

Jeśli jednak przetestować na „poziom” string drugiej, ostrzeżenie wraca. Poniższy kod ma ostrzeżenie.

my @pieces = split(/=/, $var); 
if($pieces[0] eq "PromotionNumber") { 
    #My problematic variable test 
}elsif($pieces[0] eq "Level") { 
    $promoNumber = $pieces[1]; 
} elsif ($pieces[0] eq "Type") { 
#More similar code follows 

Dlaczego Perl obchodzi, w jakiej kolejności testuję? Zauważ, że testuję kilka innych łańcuchów, które są wielokrotnymi elsif w dół w moich instrukcjach if-elsif, które nie dają tego ostrzeżenia.

Wszelkie pomysły? Naprawdę muszę wyczyścić to ostrzeżenie, aby nie zalało konsoli podczas działania. Jednak skrypt działa z ostrzeżeniami.

Dokładny błędu:

Wykorzystanie wartości niezainicjowanych w ciąg eq na japdpmrijob.pl linii 250.

dokładną linię błędu (określone przy użyciu narzędzia debugowania Perl w PerlIDE.exe) to:

if ($pieces[0] eq "PromotionNumber") { 

Mogę wydrukować $ pieces [0] i zobaczyć wartość. Tak więc wiem, że jest on określony moją wartością. Mogę również wydrukować $ pieces [1] i zobaczyć moją oczekiwaną wartość. Jeśli przetestuję najpierw $ pieces [0] eq "Level", ostrzeżenie zniknie i będę mógł uzyskać dostęp do obu zmiennych.

nadal jestem mylić ...

Wygląda jak błąd jest rzeczywiście „eq” jest oznaczona jako zmienna. Jakieś pomysły na ten temat?

Poniżej znajduje się duży fragment kodu. Zawarłem całą pętlę for i kilka zmiennych, z którymi pracuję. Zwróć uwagę na instrukcję else na końcu sekwencji if-elsif-else, dodałem ją, aby przerwać ostrzeżenie, jak odnotowano w trzeciej odpowiedzi. Ta instrukcja else wyświetla moje oczekiwane wartości za każdym razem, gdy jest wywoływane ostrzeżenie, więc wiem, że wartości są obecne.

for my $cond (@conditions) { 
    if($debug==1){print $cond."\n";} 

    # Required database variables 
    my $isRecord = 0; 
    my $promoNumber; 
    my $type; 
    my $process; 
    my $testValue; 
    my $recordOffset; 
    my $code; 
    my $subcode; 
    my $itemType; 
    my $itemValue; 

    # Function test variables 
    my $itemTypeVar; 
    my $newQualifier = 1; 

    # Database Configuration 
    my $dbApps = new Win32::ODBC("myDatabase") || die "Error: " . Win32::ODBC::Error(); 
    my @condVars = split(/\|/, $cond); 
    for my $var (@condVars) { 
     if($debug==1){print $var."\n";} 
     my @pieces = split(/=/, $var); 
     if(defined($pieces[0])){ 
      print "piece 0 defined!\n"; 
     } else { 
      print "pieces 0 not defined!\n"; 
     } 
     if(defined($pieces[1])){ 
      print "piece 1 defined!\n"; 
     } else { 
      print "piece 1 not defined!\n"; 
     } 
     if($pieces[0] eq "PromotionNumber"){ 
      $promoNumber = $pieces[1]; 
     } elsif ($pieces[0] eq "Type"){ 
      $type = $pieces[1]; 
     } elsif ($pieces[0] eq "Process"){ 
      $process = $pieces[1]; 
     } elsif ($pieces[0] eq "TestValue"){ 
      $testValue = $pieces[1]; 
     } elsif ($pieces[0] eq "RecordOffset"){ 
      $recordOffset = $pieces[1]; 
      if ($recordOffset == 0) { 
       $newQualifier = 1; } 
     } elsif ($pieces[0] eq "Code"){ 
      $code = $pieces[1]; 
     } elsif ($pieces[0] eq "SubCode"){ 
      $subcode = $pieces[1]; 
     } elsif ($pieces[0] eq "ItemType"){ 
      $itemType = $pieces[1]; 
      if($itemType eq "0") { 
       $itemTypeVar = "ItemCode"; 
      } elsif($itemType eq "1") { 
       $itemTypeVar = "ItemCode"; 
      } elsif($itemType eq "2") { 
       $itemTypeVar = "Department"; 
      } elsif($itemType eq "5") { 
       $itemTypeVar = "MixMatchCode"; 
      } elsif($itemType eq "12") { 
       $itemTypeVar = "GroupCode"; 
      } 
     } elsif ($pieces[0] eq $itemTypeVar){ 
      $itemValue = $pieces[1]; 
     } else { 
      print "$pieces[0] and $pieces[1] not used.\n"; 
     } 
     print "$var\n"; 
    } 
} 
+0

Prawie na pewno problemem jest wyrażenie '$ pieces [1]', a nie '$ pieces [0]'. Jeśli masz wartość '$ var' bez' = '(na przykład pusta linia)' split' zwróci listę pojedynczego elementu. Twoje testy dla "Typu" i "Poziomu" dotyczą tylko pierwszego elementu i będą działać, ale blok pod "Numer promocyjny" spróbuje spojrzeć na nieistniejący drugi element i wygeneruje ostrzeżenie. –

+1

Proszę podać dokładny błąd, który otrzymujesz. Nie jest jasne, która linia powoduje problem. – chepner

+0

Ponadto byłoby możliwe pokazanie nam więcej kodu (przynajmniej pętla for, która ustawia wartość '$ var'). To bardzo dziwny problem. – chepner

Odpowiedz

9

Myślę, że szukasz błędu w niewłaściwym miejscu. Aby uzyskać ostrzeżenie wyzwolone w instrukcji if-elsif-else lub innym skomplikowanym bloku kodu, starsze wersje Perla mogą zidentyfikować ostrzeżenie jako występujące w pierwszym wierszu instrukcji.

------ warn.pl ------ 
my $x = 0; 
my $y; 
if ($x == 1) {   # line 3 
} elsif ($x == 2) { 
} elsif ($x == 3) { 
} elsif ($y == 4) { # line 7 
} 

$ perl5.14.2 -w warn.pl 
Use of uninitialized value $y in numeric eq (==) at warn.pl line 7. 

$ perl5.8.6 -w warn.pl 
Use of uninitialized value in numeric eq (==) at line 3. 
+0

Mamy inny na dole, który powinien być "Złap wszystkie".Powinienem zaraz opublikować kod. Jednak moi współpracownicy i ja uważaliśmy, że kod może być gdzie indziej, ale jesteśmy całkiem pozytywni, jeśli chodzi o kombinację testów "if-elsif". – Kyle

+1

Wydaje się, że na podstawie wprowadzonych danych napotkasz linię "Level = 0", zanim napotkasz linię "ItemType". Oznacza to, że po naciśnięciu ostatniej klauzuli 'elsif'' $ itemTypeVar' nie jest jeszcze zdefiniowana. I jak zaznacza @mob, to ostrzeżenie zostanie prawdopodobnie przypisane początkowej klauzuli twojego dużego 'if-elsif-else'. – chepner

+0

@chepner DZIĘKUJEMY TAK DUŻO! Poszedłem do przodu i zaznaczałem odpowiedź moba jako poprawną, ale prawdopodobnie byłbym głupi, aby dojść do wniosku, że to była zupełnie inna zmienna powodująca mój błąd. Nie wiem, dlaczego nie pomyślałem, żeby przetestować również tę zmienną. Poprzez sprawdzenie, czy $ itemTypeVar zostało zdefiniowane przed testowaniem, wszystkie błędy zniknęły. Wielkie dzięki dla wszystkich! – Kyle

2

Możecie sprawdzić, czy $pieces[0] jest zdefiniowana, zanim zrobisz porównań. Zazwyczaj zapobiega to ostrzeżeniu:

my @pieces = split(/=/, $var); 
my $label = defined($pieces[0]) ? $pieces[0] : ""; #if not defined init to "" 
my $value = defined($pieces[1]) ? $pieces[1] : ""; 
if($label eq "PromotionNumber") { 
    $promoNumber = $value; 
} elsif ($label eq "Type") { 
#More similar code follows 
+0

Próbowałem dodać 'if (defined ($ pieces [0])) {print" DEFINED! "; } else {print "NOT DEFINED!"; } 'tuż przed problematyczną instrukcją if. Wydrukowany dla każdego pojedynczego testu, łącznie z moimi testami problemów, nadal daje mi ostrzeżenie na "if ($ pieces [0] eq" PromotionNumber ") {' linia kodu. Jestem całkowicie zaskoczony, na co narzeka Perl! – Kyle

+2

Od wersji Perl 5.10, operator '//' zastępuje 'określony ...? ...: 'konstrukcja masz -' moja $ label = $ pieces [0] // ''' – mob

+0

@mob dobrze wiedzieć. Utknąłem przy użyciu 5.8.6, więc jestem trochę w tyle w tych typach. – scrappedcola