我有位于<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
上的模块Foo::Bar::Baz
和从/some_path/Foo/Bar/Baz.pm
运行的perl脚本。脚本需要分析此文件夹中的所有模块。
如何通过文件名(/some_path/Foo/Bar
)获得模块名(Foo::Bar::Baz
)?我不能只修剪Baz.pm
结尾,而且@INC中的.pm
路径是不确定的
首先,我应该使用new_from_file的name和Module::Info方法,但是很遗憾
使用new_from_file()加载的模块将没有此信息
好像我需要一些进行静态代码分析的模块。有人知道它的名字吗?
答案 0 :(得分:4)
不需要软件包名称与加载的文件名匹配,即for the first package to。但是对于您可以正常use
甚至是一些奇怪的模块编写的任何合理的模块,Module::Metadata都可以找到此信息。通常,无论当前目录如何,都应使用绝对文件名,这可能会有所帮助。 (File::Spec和Path::Tiny可以为您提供帮助)
use strict;
use warnings;
use Module::Metadata;
my $metadata = Module::Metadata->new_from_file('/path/to/File.pm');
my $package = $metadata->name;
答案 1 :(得分:2)
我已经使用PPI来分析(和重写)perl代码。我记得,这是一个学习曲线,但效果很好。就您而言,您实际上只需要从文件中找到package <...>
语句。比这更复杂的事情,例如使用autopackage的人,以及PPI可能也无济于事。
答案 2 :(得分:2)
基本上,您不能不分析文件。 正确的方法是使用一些标准的perl模块,例如https://perldoc.pl/Module::Metadata,但是如果您想自己做,可以使用以下代码段从每个文件中提取所有名称空间(是的。文件只是一个容器,因此您内部可能会有更多软件包)。
快速而肮脏的方式:
my $PACKAGES ;
my @files = ('lib/Foo.pm','lib/Bar.pm') ;
my $row ;
map {
open PKGFILE , '<', $_ or die "Got error opening file $_: $!" ;
while ( $row = <MODULE>){
if ( $row =~ /\s*package\s+([\S]+)(.*?)[;{]/ ){
# rx modified on Grinnz review
push @{$PACKAGES->{ $_ }} , $1 ;
# last ; # <== uncomment if you are sure each file
# contains only one package
} ;
}
close PKGFILE ;
} @files ;
假设我们有两个文件:
1)lib/Foo.pm
(内部有2个软件包)
package Banana::Joe 0.003 ;
...code...
package Papaya::Frank 0.001 ;
...code...
1 ;
2)lib/Bar.pm
package Apple::Steve 0.013 ;
...code...
1 ;
$PACKAGES
将是:
{
'lib/Bar.pm' => [
'Apple::Steve'
],
'lib/Foo.pm' => [
'Banana::Joe',
'Papaya::Frank'
]
};