Документация perlfunc для do
читает
до EXPR
Использует значение EXPR
в качестве имени файла и выполняет содержимое файла как скрипт Perl.
do 'stat.pl';
так же, как
eval `cat stat.pl`;
за исключением того, что он более эффективен и лаконичен, отслеживает текущее имя файла для сообщений об ошибках, ищет каталоги @INC
и обновляет %INC
, если файл найден.
Чтобы увидеть все это в действии, скажем, C:\Cygwin\tmp\mylib\func.inc
выглядит как
sub hello {
print "Hello, world!\n";
}
1;
и мы используем его в следующей программе:
#!/usr/bin/perl
use warnings;
use strict;
# your code may have unshift @INC, ...
use lib "C:/Cygwin/tmp/mylib";
my $func = "func.inc";
do $func;
# Now we can just call it. Note that with strict subs enabled,
# we have to use parentheses. We could also predeclare with
# use subs qw/ hello /;
hello();
# do places func.inc's location in %INC
if ($INC{$func}) {
print "$0: $func found at $INC{$func}\n";
}
else {
die "$0: $func missing from %INC!";
}
Его вывод
Hello, world!
./prog: func.inc found at C:/Cygwin/tmp/mylib/func.inc
Как вы заметили, do
не всегда не кристаллическая лестница, что объясняется в документации do
:
Если do
не может прочитать файл, он возвращает undef
и устанавливает $!
на ошибку. Если do может прочитать файл, но не может скомпилировать его, он возвращает undef
и устанавливает сообщение об ошибке в $@
. Если файл успешно скомпилирован, do
возвращает значение последнего вычисленного выражения.
Чтобы проверить все эти случаи, мы больше не можем просто использовать do "func.inc"
, а
unless (defined do $func) {
my $error = $! || $@;
die "$0: do $func: $error";
}
Пояснения для каждого случая приведены ниже.
do
не может прочитать файл
Если мы переименуем func.inc
в nope.inc
и перезапустим программу, мы получим
./prog: do func.inc: No such file or directory at ./prog line 12.
do
может прочитать файл, но не может его скомпилировать
Переименуйте nope.inc
обратно в func.inc
и удалите закрывающую фигурную скобку в hello
, чтобы она выглядела как
sub hello {
print "Hello, world!\n";
1;
Запустив программу сейчас, мы получим
./prog: do func.inc: Missing right curly or square bracket at C:/Cygwin/tmp/mylib/func.inc line 4, at end of line
syntax error at C:/Cygwin/tmp/mylib/func.inc line 4, at EOF
do
может прочитать файл и скомпилировать его, но он не возвращает истинное значение.
Удалите 1;
в конце func.inc
, чтобы сделать его
sub hello {
print "Hello, world!\n";
}
Теперь вывод
./prog: do func.inc: at ./prog line 13.
Таким образом, без возвращаемого значения успех напоминает провал. Мы могли бы усложнить код, проверяющий результат do
, но лучший выбор - всегда возвращать истинное значение в конце библиотек и модулей Perl.
Обратите внимание, что программа работает правильно даже с включенной проверкой заражения (-T
). Попробуйте и посмотрите! Обязательно прочитайте Taint mode и @INC
в perlsec .