Почему Perl не печатает последний текст перед завершением работы?
Вопрос
Мой код не будет запускать последнюю строку прямо перед " exit;
- и я понятия не имею, почему.Я попытался поставить дополнительный printf $fh
линия перед exit
, но и это не сработало;он не напечатал бы ни одной строки.Все остальное печатается нормально, за исключением последних инструкций печати перед завершением.
Есть какие-нибудь подсказки, почему это происходит?Или, еще лучше, как это исправить или обойти?
if($i>0 && $i<3)
{
printf $fh "Partial match found.\n";
if($matched_uid){printf $fh "UID #: ".$arguid." exists.\n";}
if($matched_id){printf $fh "ID #: ".$argid." exists.\n";}
if($matched_uname){printf $fh "Username: ".$arguname." exists.\n";}
printf $fh "Aborting.";
exit;
}
Редактировать:
Часть кода, который я скопировал, содержала это
select $fh; $| = 1; #set auto flush
Может быть, именно поэтому мои результаты не смогли быть продублированы....
Решение
Попробуйте «Прервать. »
Это похоже на проблему с буферизацией.
Другие советы
Я дал Р.Бемроуз мой голос, но если $fh - это РУЧКА ФАЙЛА возможно, ты тоже захочешь close
это до завершения.
Кроме того, вы используете printf
ошибочно.printf это нет 'распечатать файл'.его «формат печати».
Для этого последнего примера
print $fh 'Message' ;
Это все, что тебе нужно.
printf
предназначен для использования таким образом:
printf $fh 'some format %s and more %s ' , $var , $var ;
или
printf 'some format %s and more %s ' , $var , $var ;
и это эквивалентно выполнению
print $fh sprintf 'format %s more %s' , $var , $var ;
И из-за этого вы подвергаете ненужному коду риски в случае, если какая-либо из ваших объединенных переменных расширится до содержания в них «%».Пример людей, попавших в эту ловушку, см. Вопрос:308417:Почему мой сценарий Perl удаляет символы из файла?
perldoc -f print
print FILEHANDLE LIST print LIST print Prints a string or a list of strings.
perldoc -f printf
printf FILEHANDLE FORMAT, LIST printf FORMAT, LIST Equivalent to "print FILEHANDLE sprintf(FORMAT, LIST)", except that "$\" (the output record separator) is not appended
Дальнейшее зондирование
Я продолжаю изучать вашу проблему, потому что не могу добиться выполнения вашего условия «буферизации».Все мои файлы сбрасываются правильно независимо от того, сбрасываю я их или нет.(Перл 5.10).
Вот мой фрагмент кода, который я пытаюсь:
#!/usr/bin/perl
use strict;
use warnings;
open my $fh , '>' , '/tmp/oo.txt';
my $exit_at = int(rand( 200_000 ));
print "$exit_at\n";
sleep 2;
for ( 0 .. ( $exit_at * 2 ) ){
print $fh $_;
if ( $_ == $exit_at ){
printf $fh '%n' ; # Bad Code Causes Early Death.
printf $fh 'last line';
exit;
}
if ( $_ % 1000 ){
print $fh "\n";
}
}
Я использую ваше неправильное использование printf.Закомментированная строка выдает сообщение об ошибке, поскольку она недействительна, поскольку никто не предоставил параметр «n», и она завершается:
Modification of a read-only value attempted at iotest.pl line 15.
Перед выполнением печати «последней строки» (тоже плохо, но в ней нет символов %, так что все в порядке), исключив «последнюю строку» из выходного файла.
Пожалуйста, исправьте свой printf и используйте вместо него обычный-старый-принт и посмотрите, решит ли это вашу проблему.
Perl буферизует свой вывод.Вы можете отключить автобуферизацию с помощью
local $| = 1;
Редактировать:Я как-то попал!вместо | первый раз...зафиксированный.Понятия не имею, как это произошло, они по разные стороны клавиатуры.
По вопросу о надлежащем использовании print
, - ты немного усложняешь себе жизнь.
Интерполируйте ваши переменные вместо объединения строк вместе.Используйте одну инструкцию print со списком строк для печати, а не несколько строк.
Вот один из способов:
if( $i>0 && $i<3 )
{
print $fh join "\n",
"Partial match found.",
$matched_uid ? "UID #: $arguid exists." : (),
$matched_id ? "ID #: $argid exists." : (),
$matched_uname ? "Username: $arguname exists." : (),
"Aborting.",
;
exit;
}
Тот Самый ()
на стороне false троичного оператора находится пустой список, который исчезнет, когда аргументы для объединения будут сглажены.Если бы я использовал и пустую строку (''
), каждый несоответствующий критерий привел бы к появлению дополнительной пустой строки в результатах.
Вы также можете добавить свой собственный перевод строки для каждого элемента, а затем пропустить объединение, если считаете, что это более читабельно:
print $fh
"Partial match found.\n",
$matched_uid ? "UID #: $arguid exists.\n" : '',
...
Вам нужно добавить завершающий к последнему printf.В противном случае вывод не будет сброшен на консоль.
Либо Дэвид Норман прав, либо проблема где-то в другом.Я только что набрал код внутри блока IF в интерпретаторе Perl, и он напечатал «прерывание». как и ожидалось.(У меня это сработало даже без завершающего символа новой строки.)