यह कैसे पर एक सुझाव के अधिक है नहीं यह करने के लिए। मैं सिर्फ एक बुरा समय एक बड़ा पर्ल अनुप्रयोग में एक बग खोजने के लिए किया है। अधिकांश मॉड्यूल की अपनी कॉन्फ़िगरेशन फ़ाइलें थीं। संपूर्ण रूप में कॉन्फ़िगरेशन फ़ाइलों को पढ़ने के लिए, मुझे इंटरनेट पर कहीं-कहीं पर्ल की यह एकल पंक्ति मिली:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
यह रेखा विभाजक को पहले बताए अनुसार पुन: असाइन करता है। लेकिन यह एसटीडीआईएन को भी आश्वस्त करता है।
इसका कम से कम एक साइड इफ़ेक्ट था जो मुझे ढूंढने में घंटों का समय लगता था: यह निहित फ़ाइल हैंडल को ठीक से बंद नहीं करता है (क्योंकि यह बिल्कुल भी कॉल नहीं करता है close
)।
उदाहरण के लिए, ऐसा करना:
use strict;
use warnings;
my $filename = 'some-file.txt';
my $content = do{local(@ARGV,$/)=$filename;<>};
my $content2 = do{local(@ARGV,$/)=$filename;<>};
my $content3 = do{local(@ARGV,$/)=$filename;<>};
print "After reading a file 3 times redirecting to STDIN: $.\n";
open (FILE, "<", $filename) or die $!;
print "After opening a file using dedicated file handle: $.\n";
while (<FILE>) {
print "read line: $.\n";
}
print "before close: $.\n";
close FILE;
print "after close: $.\n";
का परिणाम:
After reading a file 3 times redirecting to STDIN: 3
After opening a file using dedicated file handle: 3
read line: 1
read line: 2
(...)
read line: 46
before close: 46
after close: 0
अजीब बात यह है, कि $.
हर फाइल के लिए एक-एक करके लाइन काउंटर बढ़ाया जाता है। यह रीसेट नहीं है, और इसमें लाइनों की संख्या नहीं है। और कम से कम एक पंक्ति पढ़ने तक दूसरी फ़ाइल खोलने पर इसे शून्य पर रीसेट नहीं किया जाता है। मेरे मामले में, मैं कुछ इस तरह कर रहा था:
while($. < $skipLines) {<FILE>};
इस समस्या के कारण, स्थिति झूठी थी क्योंकि लाइन काउंटर ठीक से रीसेट नहीं किया गया था। मुझे नहीं पता कि यह बग है या बस गलत कोड ... इसके अलावा close;
ओडर कॉल करने से भी close STDIN;
मदद नहीं मिलती है।
मैंने इस अपठनीय कोड को खुले, स्ट्रिंग संयोजन और बंद का उपयोग करके बदल दिया। हालांकि, ब्रैड गिल्बर्ट द्वारा पोस्ट किया गया समाधान भी काम करता है क्योंकि यह इसके बजाय एक स्पष्ट फ़ाइल हैंडल का उपयोग करता है।
शुरुआत में तीन पंक्तियों को प्रतिस्थापित किया जा सकता है:
my $content = do{local $/; open(my $f1, '<', $filename) or die $!; my $tmp1 = <$f1>; close $f1 or die $!; $tmp1};
my $content2 = do{local $/; open(my $f2, '<', $filename) or die $!; my $tmp2 = <$f2>; close $f2 or die $!; $tmp2};
my $content3 = do{local $/; open(my $f3, '<', $filename) or die $!; my $tmp3 = <$f3>; close $f3 or die $!; $tmp3};
जो फ़ाइल हैंडल को ठीक से बंद कर देता है।