Це більше пропозиція щодо того, як НЕ робити цього. Мені просто не вдалося знайти помилку в досить великому додатку Perl. Більшість модулів мали власні файли конфігурації. Щоб прочитати конфігураційні файли в цілому, я знайшов цей єдиний рядок Perl десь в Інтернеті:
# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};
Він перепризначає роздільник рядків, як пояснено раніше. Але він також перепризначає STDIN.
Це мало принаймні один побічний ефект, який коштував мені годин на пошук: він не закриває неявно оброблену файлу належним чином (оскільки вона взагалі не дзвонить 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};
що правильно закриває ручку файлу.