2014-11-06 4 views
6

내가 받고 있어요 :펄 경고 : 초기화되지 않은 값의 사용에 가입하거나 문자열

"Use of uninitialized value in join or string at ./test_script.pl line 69, <fh> line 91." 

이 경고를 생성하는 코드는 여기에 있습니다 : 그것은 "인쇄에서 오는

# Write results of SQL execution to output file 
if ([email protected]) { print "\n DB Error : ", [email protected]; exit; } 
open(FH, ">$output_file") or 
     die "\n cannot write to the file $output_file. Check the file permissions"; 
while(my @row= $sth->fetchrow_array) { 
     print FH join($delimiter, @row). "\n"; 
} 

.. "join".... "while"블록에 있지만, 그것을 일으키는 원인과 해결 방법에 대해 100 % 확실하지 않습니다.

$ 구분 기호는 이전에 my $ delimiter = "|"로 초기화되었습니다. @row는 이전 줄의 $ sth 연산에서 값을 가져옵니다.

경고의 "< fh> line 91"부분에 표시된 것처럼 @row 값과 관련하여 "타이밍"문제입니까, 아니면 처리중인 실제 SQL 쿼리 파일에 있습니까? 내가 경고를 피할 수있는 방법에 대한 아이디어가 있습니까? BTW, 스크립트가 제대로 작동합니다. 큰 데이터 세트에 많은 양의 경고를 생성하는 각 @row 값에 대해 경고가 생성됩니다 ...

+0

귀하의 검색어는 어떤 모습입니까, 아니면 검색어를 생성 한 코드입니까? – SBH

+1

$ 구분 기호에 값이 있음을 증명하십시오. print 앞에'print '구분 기호 >>> $ delimiter <<< \ n ";' – toolic

+4

추측했다면'@ row'의 열 중 하나가'NULL'입니다. – nandhp

답변

11

@row에는 정의되지 않은 값이있는 요소가 포함될 수 있습니다. 아마도 데이터베이스에있는 하나 이상의 열이 @row인데 NULL 이었기 때문일 수 있습니다.

perl -we 'my @array = ("Hello",undef,"world!"); print join("|",@array) . "\n";' 

생산할 예정이다 출력은 다음과 같습니다 : join가 노력하고 있기 때문에 이런 일이 발생

Use of uninitialized value $array[1] in join or string at -e line 1. 
Hello||world! 

이유는 여전히이 같은 간단한 펄 한 줄에 join를 사용하는 동안 동작은 모방 할 수있다 "undefined"에서 "defined"로 업그레이드하지 않고 문자열을 지정하지 않는 값을 조인하십시오. 문자열 undef이 의도하지 않았거나 올바르지 않을 수 있음을 경고하는 경고 메시지를 생성합니다.

더 간단한 예는이 될 수있다 : 우리가 문자열로 정의되지 않은 값을 보간하고 있기 때문에

$ perl -we 'my $scalar; print "$scalar\n";' 
Use of uninitialized value $scalar in concatenation (.) or string at -e line 1. 

가 다시 말하지만, 우리는 경고를 얻을. 보간으로 인해 문자열이 만들어지며 정의되지 않은 값의 문자열로 인해 일반적으로 실수로 경고 한 경고가 표시됩니다. 당신이 빈 문자열로 undef 's의 업그레이드를 자동으로 괜찮다면

, 당신이 할 수 있습니다 :

print FH join($delimiter, map { defined ? $_ : '' } @row) . "\n"; 

이 사전 프로세스 @rowjoin()에 전달하기 전에. @row의 각 요소에 대해 요소에 정의되지 않은 값이있는 경우 해당 값은 정의되지만 시각적으로 조용한 빈 문자열로 대체됩니다.

다른 가능성은 $delimiter이 정의되지 않은 것입니다. 이를 인쇄하여 테스트 해보십시오. 실제로 문제가 해결 되었다면 실제로 해결해야 할 단계는 실제로 값이 포함되어 있는지 확인하는 것입니다.

엄격한 어휘 범위에서 경고음을 들리지 않게하면 좋을 수도 있지만 철학적 관점에서 볼 때 하나의 방법으로 원인을 제거하고 다른 하나는 증상 중 하나를 제거합니다. 다른 곳에서 설명한 "no warnings 'uninitialized'; 방법은 그 일을 수행하므로 경고가 사라집니다.당신은 당신이 뭔가를 완벽하게하고 있다는 것을 알 때 이것을 할 것입니다. 그러나 Perl은 실수로 여러 번 말하기 때문에 경고 할 것입니다. 이것은 그러한 상황 일 수 있습니다. 정의되지 않은 값의 자동 문자열 지정이 join 내부에서 발생하게되면 완벽하게 만족할 수 있습니다. 그리고 그러한 경우라면, 계속해서 경고를 스퀠 핑하십시오. 가장 중요한 것은 당신이 의미하는 것이 무엇인지 알았고, 무엇이 그것을 일으키는 지 확인한 다음 그것에 대해 무엇을해야하는지에 대해 정보에 입각 한 결정을 내리는 것입니다.

+1

누구나이를 발견하면 표시된대로 정의 된 사용이 모호합니다. 그것은 map {defined $ _? $ _ : ''} – mark

+0

'perl'은 여기에 모호성이 없으며'defined'는 다른 매개 변수가없는 경우 매개 변수로'$ _'를 사용하는 것으로 되돌아갑니다. 이에 대해서는'perldoc -f defined'에서 논의합니다. 삼항 연산자의 사용은 모호하지 않습니다. 그리고'map'은 iterating하고있는리스트 요소의 별칭으로'$ _'을 채 웁니다. 이것은 스타일 문제에 관한 것으로, 아마도 PBP의 어딘가에서 언급 될 수 있습니다. – DavidO

+0

사실, 그렇습니다. PBP 문제는 105-107 페이지의 * Iterator Variables * 표제에 들어 있습니다. 이 PBP 제안은 모호함을 인용하는 것이 아니라 가독성을 나타냅니다. 가독성이 문제라면 우려하지 않습니다. – DavidO