do BLOCK

并非真正的函数。返回 BLOCK 指示的命令序列中最后一个命令的值。当被 whileuntil 循环修饰符修改时,在测试循环条件之前执行一次 BLOCK。(在其他语句中,循环修饰符首先测试条件。)

do BLOCK 不算作循环,因此循环控制语句 nextlastredo 不能用于离开或重新启动块。有关替代策略,请参阅 perlsyn

do EXPR

使用 EXPR 的值作为文件名,并将文件的内容作为 Perl 脚本执行

# load the exact specified file (./ and ../ special-cased)
do '/foo/stat.pl';
do './stat.pl';
do '../foo/stat.pl';

# search for the named file within @INC
do 'stat.pl';
do 'foo/stat.pl';

do './stat.pl' 在很大程度上类似于

eval `cat stat.pl`;

除了它更简洁、不运行外部进程并跟踪当前文件名以获取错误消息之外。它还不同于使用 do FILE 评估的代码无法看到封闭作用域中的词法;eval STRING 可以。但是,它相同,因为它每次调用都会重新解析文件,所以你可能不想在循环中执行此操作。

对相对路径(除了 ./../)使用 do,如

do 'foo/stat.pl';

将搜索 @INC 目录,如果找到该文件,则更新 %INC。有关这些变量,请参阅 "@INC" in perlvar"%INC" in perlvar。特别是,请注意,虽然历史上 @INC 包含 '.'(当前目录),使这两个用例等效,但不再一定是这种情况,因为 '.' 从 perl 5.26.0 版本开始默认情况下不包含在 @INC 中。相反,perl 现在会发出警告

do "stat.pl" failed, '.' is no longer in @INC;
did you mean do "./stat.pl"?

如果 do 可以读取文件但无法编译它,则它会返回 undef 并设置 $@ 中的错误消息。如果 do 无法读取文件,则它会返回 undef 并将 $! 设置为错误。始终先检查 $@,因为编译可能会以一种也设置 $! 的方式失败。如果文件编译成功,则 do 会返回所评估的最后一个表达式的值。

最好使用 userequire 运算符来包含库模块,这些运算符还会执行自动错误检查,并在出现问题时引发异常。

你可能想使用 do 来读取程序配置文件。可以这样进行手动错误检查

# Read in config files: system first, then user.
# Beware of using relative pathnames here.
for $file ("/share/prog/defaults.rc",
           "$ENV{HOME}/.someprogrc")
{
    unless ($return = do $file) {
        warn "couldn't parse $file: $@" if $@;
        warn "couldn't do $file: $!"    unless defined $return;
        warn "couldn't run $file"       unless $return;
    }
}