【问题标题】:Perl problem 'require' the same filePerl 问题“需要”同一个文件
【发布时间】:2026-01-14 09:05:02
【问题描述】:

我在 perl 中有一个共享模块。主程序需要两个文件,第一个是共享文件(我们称之为“X”),第二个是一个“包”文件。文件“X”也使用“require”包含在“package”文件中。当我编译这个程序时,它给了我以下错误:

Undefined subroutine &main::trim called at testing.pl line 8.

我的理解是 perl 找不到 trim() 模块。如果我不包含包文件,那么这将毫无问题地运行。

谁能解释这个问题?

这些是我的代码:

主程序:testing.pl

#!/usr/bin/perl -w

use strict;
use postgres;

require "shared.pl";

trim("als");

包文件:postgres.pm

#!/usr/bin/perl

package postgres;

use strict;
use DBI;

require "shared.pl";

1;

共享文件:shared.pl

#!/usr/bin/perl

# =============
# shared module 
# =============

use strict;

sub trim($)
{
}

1;

【问题讨论】:

    标签: perl


    【解决方案1】:

    如果模块不使用package,您需要do 而不是require。见What is the difference between library files and modules?

    do "shared.pl" or die $@;
    

    你真的应该创建一个合适的模块,一个带有package 语句的模块。

    package Shared;
    
    use strict;
    use warnings;
    
    our @EXPORT = qw( trim );
    use Exporter qw( import );
    
    sub trim { ... }
    
    1;
    

    将文件命名为Shared.pm 并使用use Shared; 加载它。

    【讨论】:

    • 感谢您指出这一点。显然,关于如何在 perl 中正确编码,我还有很多东西要学。
    【解决方案2】:

    默认情况下,require 只会加载一次文件。在这种情况下,该时间来自postgres 包中的文件postgres.pm。所以trim 子例程在postgres 命名空间中被定义为&postgres::trim

    一种解决方法是在 testing.pl 文件中使用完全限定的子例程名称:

    postgres::trim("als");       # not trim("als")
    

    另一种解决方法是破解%INC 表(跟踪哪些模块/文件已经被use'd 和require'd 的变量),以便您可以将shared.pl 重新加载到主包中:

    use postgres;
    
    delete $INC{"shared.pl"};
    require "shared.pl";
    

    第三种解决方法是将trim 函数从postgres 包导出到主包。 Exporter 模块的文档很好地介绍了为什么以及如何做到这一点。

    # in postgres.pm
    *main::trim = *trim;
    
    # or in testing.pl
    *trim = *postgres::trim;
    trim("als");
    

    【讨论】:

    • delete $INC{"shared.pl"}; waaaa?不!
    最近更新 更多