如我们所知,Perl使用包含目录名的@INC数组来确定在哪里搜索Perl模块文件。
@INC
在StackOverflow上似乎没有一个全面的“@INC”常见问题类型的帖子,所以这个问题是一个。
我们将看看这个数组的内容是如何构造的,以及如何操作它来影响Perl解释器在哪里找到模块文件。
Perl解释器是使用特定的@INC默认值编译。要找到这个值,运行env -i perl -V命令(env -i忽略PERL5LIB环境变量-参见#2),在输出中你将看到如下内容:
env -i perl -V
env -i
PERL5LIB
$ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 . 李< /引用> < / >
$ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
注意结尾的.;这是当前目录(不一定与脚本的目录相同)。它在Perl 5.26+中缺失,并且当Perl运行-T(启用污点检查)时。
.
-T
要在配置Perl二进制编译时更改默认路径,请设置配置选项otherlibdirs:
otherlibdirs
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
PERLLIB
Perl将shell的环境变量PERL5LIB(如果没有定义,则使用PERLLIB)中包含的目录列表(以冒号分隔)预先挂起@INC。在PERL5LIB和PERLLIB环境变量生效后,执行perl -V命令查看@INC的内容。
perl -V
$ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 . 李< /引用> < / > -I命令行选项 Perl在@INC前挂起一个目录列表(冒号分隔),作为-I命令行选项的值传递。这可以通过三种方式完成,通常使用Perl选项: 在命令行上传递它: perl -I /my/moduledir your_script.pl Pass it via the first line (shebang) of your Perl script: #!/usr/local/bin/perl -w -I /my/moduledir Pass it as part of PERL5OPT (or PERLOPT) environment variable (see chapter 19.02 in Programming Perl) Pass it via the lib pragma Perl pre-pends @INC with a list of directories passed in to it via use lib. In a program: use lib ("/dir1", "/dir2"); 在命令行中: perl -Mlib=/dir1,/dir2 你也可以通过__ABC1删除@INC中的目录. 你可以直接操作@INC作为一个常规的Perl数组。 注意:由于在编译阶段使用了@INC,这必须在use MyModule语句之前的BEGIN {}块中完成。 通过unshift @INC, $dir将目录添加到开头。 通过push @INC, $dir将目录添加到末尾。 使用Perl数组可以做任何其他事情。 李< / ul > < / >
$ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
-I命令行选项
-I
Perl在@INC前挂起一个目录列表(冒号分隔),作为-I命令行选项的值传递。这可以通过三种方式完成,通常使用Perl选项:
perl -I /my/moduledir your_script.pl
Pass it via the first line (shebang) of your Perl script:
#!/usr/local/bin/perl -w -I /my/moduledir
Pass it as part of PERL5OPT (or PERLOPT) environment variable (see chapter 19.02 in Programming Perl)
PERL5OPT
PERLOPT
Pass it via the lib pragma
lib
Perl pre-pends @INC with a list of directories passed in to it via use lib.
use lib
In a program:
use lib ("/dir1", "/dir2");
在命令行中:
perl -Mlib=/dir1,/dir2
你也可以通过__ABC1删除@INC中的目录.
注意:由于在编译阶段使用了@INC,这必须在use MyModule语句之前的BEGIN {}块中完成。
use MyModule
BEGIN {}
通过unshift @INC, $dir将目录添加到开头。
unshift @INC, $dir
通过push @INC, $dir将目录添加到末尾。
push @INC, $dir
使用Perl数组可以做任何其他事情。
注意:目录从未移位到@INC,按照答案中列出的顺序,例如默认的@INC在列表的最后,前面是PERL5LIB,前面是-I,前面是use lib和直接的@INC操作,后两者在Perl代码中按照它们的顺序混合。
在Stack Overflow上似乎没有一个全面的@INC faq类型的帖子,所以这个问题是一个。
如果一个目录中的模块需要被站点上的许多/所有脚本使用,特别是由多个用户运行,则该目录应该包含在编译成Perl二进制文件的默认@INC中。
注意:请注意常见的Unix环境变量陷阱——例如,在某些情况下,以特定用户运行脚本并不保证在该用户的环境设置下运行它们,例如通过su。 < / p >
su
如果目录中的模块只需要在特定的情况下使用(例如,当脚本在开发/调试模式下执行时),您可以手动设置PERL5LIB,或将-I选项传递给perl。
如果模块只需要用于特定的脚本,由all用户使用它们,则在程序本身中使用use lib/no lib pragmas。当需要在运行时动态确定要搜索的目录时,也应该使用它-例如,从脚本的命令行参数或脚本的路径(参见FindBin模块,非常好的用例)。
no lib
直接操作@INC的另一个用例是能够添加子例程引用或对象引用(是的,Virginia, @INC可以包含自定义Perl代码,而不仅仅是目录名,如在@INC中什么时候调用子例程引用?)。
除了上面列出的位置之外,OS X版本的Perl还有两种方法:
/图书馆/ Perl / x。xx / AppendToPath文件。该文件中列出的路径在运行时被追加到@INC。
/图书馆/ Perl / x。xx / PrependToPath文件。该文件中列出的路径在运行时被加在@INC前面。
正如前面所说,@INC是一个数组,您可以随意添加任何内容。
我的CGI REST脚本看起来像这样:
#!/usr/bin/perl use strict; use warnings; BEGIN { push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm'; } use Modules::Rest; gone(@_);
Rest.pm导出子例程gone。