如何从 Perl 中的部分命名空间动态发现包?

发布于 2024-09-04 02:50:19 字数 164 浏览 2 评论 0 原文

我的目录结构如下所示:

Foo::Bar::Baz::1 Foo::Bar::Baz::2 等

我可以列出类似以下内容的包:

use Foo::Bar::Baz;

谢谢!

编辑:更清楚地说明了模块是什么。

I have a directory structure that looks like:

Foo::Bar::Baz::1
Foo::Bar::Baz::2 etc

Can I list the packages from something like:

use Foo::Bar::Baz;

Thanks!

Edit: Made it more clear what the modules are.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

找个人就嫁了吧 2024-09-11 02:50:19

如果您想加载包含路径中具有特定前缀的所有模块(例如 a::b::c 下的所有模块,您可以使用 Module::Find

例如:

use Module::Find 'useall';

my @loaded = useall 'Foo::Bar::Baz';  # loads everything under Foo::Bar::Baz

这取决于您使用以下命令设置的 @INC 路径必要的目录,因此首先进行任何所需的操作(例如使用use lib)。

If you want to load all modules in your include path with a certain prefix (e.g. everything under a::b::c, you can use Module::Find.

For example:

use Module::Find 'useall';

my @loaded = useall 'Foo::Bar::Baz';  # loads everything under Foo::Bar::Baz

This depends on your @INC path being set up with the necessary directories, so do any required manipulation (e.g. with use lib) first.

奢欲 2024-09-11 02:50:19

通常,像 a/b/c.pl 这样的脚本不会有 main 之外的命名空间。也许您正在考虑使用诸如 a/b/c.pm 之类的名称来发现模块(这是一个不好的名称,因为小写的包名称通常是为 Perl 内部保留的)。

但是,给定目录路径,您可以使用 潜在 Perl 模块>文件::查找:

use strict;
use warnings;
use File::Find;
use Data::Dumper;

my @modules;
sub wanted
{
    push @modules, $_ if m/\.pm$/
}
find(\&wanted, 'A/B');

print "possible modules found:\n";
print Dumper(\@modules)'

Normally a script such as a/b/c.pl won't have a namespace other than main. Perhaps you are thinking of discovering modules with names such as a/b/c.pm (which is a bad name, since lower-cased package names are generally reserved for Perl internals).

However, given a directory path, you can look for potential Perl modules using File::Find:

use strict;
use warnings;
use File::Find;
use Data::Dumper;

my @modules;
sub wanted
{
    push @modules, $_ if m/\.pm$/
}
find(\&wanted, 'A/B');

print "possible modules found:\n";
print Dumper(\@modules)'
蓝色星空 2024-09-11 02:50:19

这可能有点过头了,但是您可以在加载模块之前和之后检查符号表并查看发生了什么变化:

use strict; use warnings;
my %original = map { $_ => 1 } get_namespaces("::");
require Inline;
print "New namespaces since 'require Inline' call are:\n";
my @new_namespaces = sort grep !defined $original{$_}, get_namespaces("::");
foreach my $new_namespace (@new_namespaces) {
  print "\t$new_namespace\n";
}

sub get_namespaces {
  # recursively inspect symbol table for known namespaces
  my $pkg = shift;
  my @namespace = ();
  my %s = eval "%" . $pkg;
  foreach my $key (grep /::$/, keys %s) {
    next if $key eq "main::";
    push @namespace, "$pkg$key", get_namespaces("$pkg$key");
  }
  return @namespace;
}

New namespaces since 'require Inline' call are:
        ::AutoLoader::
        ::Config::
        ::Digest::
        ::Digest::MD5::
        ::Dos::
        ::EPOC::
        ::Exporter::
        ::Exporter::Heavy::
        ::File::
        ::File::Spec::
        ::File::Spec::Cygwin::
        ::File::Spec::Unix::
        ::File::Spec::Win32::
        ::Inline::Files::
        ::Inline::denter::
        ::Scalar::
        ::Scalar::Util::
        ::Socket::
        ::VMS::
        ::VMS::Filespec::
        ::XSLoader::
        ::vars::
        ::warnings::register::

This might be overkill, but you can inspect the symbol table before and after loading the module and see what changed:

use strict; use warnings;
my %original = map { $_ => 1 } get_namespaces("::");
require Inline;
print "New namespaces since 'require Inline' call are:\n";
my @new_namespaces = sort grep !defined $original{$_}, get_namespaces("::");
foreach my $new_namespace (@new_namespaces) {
  print "\t$new_namespace\n";
}

sub get_namespaces {
  # recursively inspect symbol table for known namespaces
  my $pkg = shift;
  my @namespace = ();
  my %s = eval "%" . $pkg;
  foreach my $key (grep /::$/, keys %s) {
    next if $key eq "main::";
    push @namespace, "$pkg$key", get_namespaces("$pkg$key");
  }
  return @namespace;
}

New namespaces since 'require Inline' call are:
        ::AutoLoader::
        ::Config::
        ::Digest::
        ::Digest::MD5::
        ::Dos::
        ::EPOC::
        ::Exporter::
        ::Exporter::Heavy::
        ::File::
        ::File::Spec::
        ::File::Spec::Cygwin::
        ::File::Spec::Unix::
        ::File::Spec::Win32::
        ::Inline::Files::
        ::Inline::denter::
        ::Scalar::
        ::Scalar::Util::
        ::Socket::
        ::VMS::
        ::VMS::Filespec::
        ::XSLoader::
        ::vars::
        ::warnings::register::
月亮是我掰弯的 2024-09-11 02:50:19

需要明确的是,您是否正在查看随机 Perl 代码中的随机包?

或者对于 Perl 模块,例如“a/b/c/d1.pm”和模块“a::b::c::d1”?

无论哪种情况,您都不能使用单个“use”语句来加载所有它们。

您需要做的是使用 globFile::Find 查找所有适当的文件。

在第一种情况(模块)中,您可以通过 require-ing 每个文件来加载它们,或者通过将文件名转换为模块名称(s#/#::#g; s# \.pm$##;) 并分别在每个模块上调用 use

至于嵌套在随机 Perl 文件中的实际包,这些包可以是:

  • 通过 grep 每个文件列出(同样,通过 globFile::Find 找到) for /^package (.*);/

  • 实际是通过对每个文件执行require $file来加载的。

    在这种情况下,请注意 a/b/c/1.pl 中每个包的包名称不需要与“ a::b::c" - 例如它们可以由文件作者“p1”、“a::p1”或“a::b::c::p1_something”命名。

Just to be clear, are you looking at random packages in random Perl code?

Or for Perl modules, e.g. "a/b/c/d1.pm" with module "a::b::c::d1"?

In either case, you can not use a single "use" statement to load them all.

What you need to do is to find all the appropriate files, using either glob or File::Find.

In the first case (modules), you can then load them either by require-ing each file, OR by converting filename into module name (s#/#::#g; s#\.pm$##;) and calling use on each module individually.

As far as actual packages nested in random Perl files, those packages can be:

  • Listed by grepping each file (again, found via glob or File::Find) for /^package (.*);/

  • Actually loaded by executing require $file for each file.

    In this case, please note that the package name for each of those packages in a/b/c/1.pl will NOT need to be related to "a::b::c" - e.g. they CAN be named by the file author "p1", "a::p1" or "a::b::c::p1_something".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文