Perl 如何在加载的模块中使用Smart::Comments而不更改其源?
如何指定为原始脚本以及它直接加载的任何模块加载Smart::Comments。然而,由于它是一个源过滤器,如果将它应用到由每个其他加载的模块加载的每个模块,可能会造成严重破坏 例如,我的脚本包括Perl 如何在加载的模块中使用Smart::Comments而不更改其源?,perl,command-line,module,Perl,Command Line,Module,如何指定为原始脚本以及它直接加载的任何模块加载Smart::Comments。然而,由于它是一个源过滤器,如果将它应用到由每个其他加载的模块加载的每个模块,可能会造成严重破坏 例如,我的脚本包括 use Neu::Image; 我也想为Neu::Image加载,但要指定 $ perl -MSmart::Comments script.pl 当然,这只会启用smart 应用程序文件中的注释 本身,而不是在 应用程序加载 我已经看了一些其他的东西: (我查了一下 “模块”一词) 解决方法 正
use Neu::Image;
我也想为Neu::Image
加载,但要指定
$ perl -MSmart::Comments script.pl
当然,这只会启用smart
应用程序文件中的注释
本身,而不是在
应用程序加载
我已经看了一些其他的东西:
- (我查了一下 “模块”一词)
正如gbacon提到的,Smart::Comments提供了一个环境变量选项,允许打开或关闭它。但是,如果可能的话,我希望能够在不修改原始源代码的情况下打开它。您几乎肯定希望将
使用Smart::Comments
添加到包含此类内容的模块中,然后通过适当设置$Smart\u Comments
偷吃东西,import
-劫持猴子补丁是疯狂的行为
但也许你对这类事情感兴趣。假设你有Foo.pm
:
package Foo;
use Exporter 'import';
our @EXPORT = qw/ foo /;
#use Smart::Comments;
sub foo {
my @result;
for (my $i = 0; $i < 5; $i++) {
### $i
push @result => $i if $i % 2 == 0;
}
wantarray ? @result : \@result;
}
1;
(请原谅我的紧凑性:我把它缩小了,这样它就可以放在一块未经滚压的砖里。)
输出:
$ ./run-foo
### $i: 0
### $i: 1
### $i: 2
### $i: 3
### $i: 4
024
美元/润富
###$i:0
###$i:1
###$i:2
###$i:3
###$i:4
024
“万岁
我们可以用我们自己的或修改过的资源替代。代码监视是否尝试需要程序直接使用的
模块。点击时,inject\u smart\u comments
返回一个迭代器,每次生成一行。当这个狡猾、巧妙的迭代器看到包声明时,它会在块中附加一个看起来无辜的use Smart::Comments
,使其看起来就像一直在模块的源代码中一样
例如,通过尝试用正则表达式解析Perl代码,如果包声明本身不在一行上,代码就会中断。调味。这个想法似乎没有任何意义。如果您正在模块中使用,为什么不想在该模块的源代码中使用Smart::Comments?即使您可以通过
-M
应用于脚本中加载的所有模块,也可能不是一个好主意,因为:
- 您正在混淆模块正在使用智能注释这一事实,因为它们的源代码中没有包含
行use
- 您可能会从脚本中
使用的模块中引入奇怪的行为,这些模块碰巧有看起来像智能注释,但实际上不是。如果一个模块不包含智能注释,你不应该强迫它们进入它的喉咙
在使用该模块的每个模块中使用该模块,然后在不需要输出时使用环境变量抑制它们
同样,正如他所说的,用一些“藏匿大口、进口劫持猴子修补”的疯狂行为来实现这一点仍然是可能的,但这需要大量的工作。我认为,如果一开始不是一个好主意,就没有人会按照这些思路为你提供解决方案。“有些男人不寻求任何合乎逻辑的东西。他们不能被收买、欺负、推理或谈判。有些男人只想看着世界燃烧。”@gbacon:你是指我使用Smart::Comments吗?我只是想找到一种“安全”玩火的方法你的问题真的是“如何在我加载的每个模块中使用Smart::Comments而不更改它们的源”?@brian实际上是的。在不引起“世界燃烧”的情况下这是可能的吗?你为什么不想改变来源?你的处境是不允许的吗?谢谢。我忘了环境开关了。哇!我是说,哇!感谢gbacon,Perl大师!感谢您对@INC hooks的引用。我真的不想让你或其他人做很多工作。我想可能有更简单的办法。哇,真是太神奇了!错误:模块必须在当前目录中。如书面所述,它不会搜索@INC
。感谢您的回答。对我来说,Smart::注释仅用于调试。从布赖恩的评论中,我开始认为还有另一种方法可以做到这一点,但并不复杂。我不会要求任何人付出很多努力。
$ perl -MFoo -e 'print foo, "\n"'
024
#! /usr/bin/perl
use warnings;
use strict;
BEGIN {
unshift @INC => \&inject_smart_comments;
my %direct;
open my $fh, "<", $0 or die "$0: open: $!";
while (<$fh>) {
++$direct{$1} if /^\s*use\s+([A-Z][:\w]*)/;
}
close $fh;
sub inject_smart_comments {
my(undef,$path) = @_;
s/[\/\\]/::/g, s/\.pm$// for my $mod = $path;
if ($direct{$mod}) {
open my $fh, "<", $path or die "$0: open $path: $!";
return sub {
return 0 unless defined($_ = <$fh>);
s{^(\s*package\s+[A-Z][:\w]*\s*;\s*)$}
{$1 use Smart::Comments;\n};
return 1;
};
}
}
}
use Foo;
print foo, "\n";
$ ./run-foo
### $i: 0
### $i: 1
### $i: 2
### $i: 3
### $i: 4
024