在Perl中使用filehandles更改活动运行的代码

在Perl中使用filehandles更改活动运行的代码,perl,file-handling,Perl,File Handling,我一直在学习Perl中的文件句柄,我很想知道是否有办法在程序运行时更改其源代码。例如,我创建了一个名为“dynamic.pl”的脚本,其中包含以下内容: use strict; use warnings; open(my $append, ">>", "dynamic.pl"); print $append "print \"It works!!\\n\";\n"; 这个程序添加了行 print "It works!!\n"; 在它自己的源文件末尾,我希望一旦添加了这一行,它就

我一直在学习Perl中的文件句柄,我很想知道是否有办法在程序运行时更改其源代码。例如,我创建了一个名为“dynamic.pl”的脚本,其中包含以下内容:

use strict;
use warnings;

open(my $append, ">>", "dynamic.pl");
print $append "print \"It works!!\\n\";\n";
这个程序添加了行

print "It works!!\n";
在它自己的源文件末尾,我希望一旦添加了这一行,它就会执行并输出“Itworks!!”

好吧,它确实正确地将行附加到源文件中,但它不会当场执行它


因此,我假设当perl执行一个程序时,它会将其加载到内存中并从内存中运行,但我的问题是,有没有一种方法可以访问这个加载版本的程序,这样您就可以拥有一个可以在运行时改变自身的程序?

缺少的部分是。这将编译“计算”任何字符串作为代码

my $string = q[print "Hello, world!";];
eval $string;
此字符串可以来自任何源,包括文件句柄

它也不必是一个单独的语句。如果要修改程序的运行方式,可以替换其子例程

use strict;
use warnings;
use v5.10;

sub speak { return "Woof!"; }
say speak();

eval q[sub speak { return "Meow!"; }];
say speak();
您将从中得到一个
子例程speak redefined
警告。可以使用
无警告“重定义”
来禁止该操作

显然,这是一个重大的安全漏洞。这里有很多,很多,很多事情要考虑,太长的答案,我强烈建议你不要这样做,找到一个更好的解决方案,无论你试图解决这样的问题。


减轻潜在损坏的一种方法是使用该模块。这类似于
eval
,但限制了可用的内置函数。它决不是解决安全问题的灵丹妙药。

您需要的缺失部分是。这将编译“计算”任何字符串作为代码

my $string = q[print "Hello, world!";];
eval $string;
此字符串可以来自任何源,包括文件句柄

它也不必是一个单独的语句。如果要修改程序的运行方式,可以替换其子例程

use strict;
use warnings;
use v5.10;

sub speak { return "Woof!"; }
say speak();

eval q[sub speak { return "Meow!"; }];
say speak();
您将从中得到一个
子例程speak redefined
警告。可以使用
无警告“重定义”
来禁止该操作

显然,这是一个重大的安全漏洞。这里有很多,很多,很多事情要考虑,太长的答案,我强烈建议你不要这样做,找到一个更好的解决方案,无论你试图解决这样的问题。


减轻潜在损坏的一种方法是使用该模块。这类似于
eval
,但限制了可用的内置函数。这绝不是解决安全问题的灵丹妙药。

这里几乎肯定有更好的方法来实现您的最终目标。但是,您可以递归地进行exec()或system()调用——如果需要返回值,可以调用后者。一定要设置一些条件,否则多米诺骨牌会不断掉落。再一次,你应该重新思考这个问题,除非这只是某种练习,或者我不明白

每次调用都应执行文件的最新状态;还请确保在每次调用之前关闭该文件

i、 e

exec(“dynamic.pl”)

my retval; 
retval = system("perl dynamic.pl");

永远不要使用eval。

这里几乎肯定有更好的方法来实现您的最终目标。但是,您可以递归地进行exec()或system()调用——如果需要返回值,可以调用后者。一定要设置一些条件,否则多米诺骨牌会不断掉落。再一次,你应该重新思考这个问题,除非这只是某种练习,或者我不明白

每次调用都应执行文件的最新状态;还请确保在每次调用之前关闭该文件

i、 e

exec(“dynamic.pl”)

my retval; 
retval = system("perl dynamic.pl");

永远不要使用eval。

带有关于各种问题的警告,您可以重新加载模块

有这样的包,例如。然后,您可以编写要在模块中更改的代码,在运行时更改源代码,并重新加载它

您可以手动将其从
%INC
中删除,然后从
require
中删除,如

# ... change source code in the module ...
delete $INC{'ModuleWithCodeThatChages.pm'};
require ModuleWithCodeThatChanges;
我能想到这样做的唯一原因是实验和游戏。否则,做这样的事情会有各种各样的顾虑,不管你的目标是什么,都有其他方法来实现它


注意问题确实指定了文件句柄。然而,我并不认为这与我所看到的问题的核心有关,即在运行时修改代码。

通过对各种问题的警告,您可以重新加载模块

有这样的包,例如。然后,您可以编写要在模块中更改的代码,在运行时更改源代码,并重新加载它

您可以手动将其从
%INC
中删除,然后从
require
中删除,如

# ... change source code in the module ...
delete $INC{'ModuleWithCodeThatChages.pm'};
require ModuleWithCodeThatChanges;
我能想到这样做的唯一原因是实验和游戏。否则,做这样的事情会有各种各样的顾虑,不管你的目标是什么,都有其他方法来实现它


注意问题确实指定了文件句柄。然而,我并不认为这与我所看到的在运行时修改代码这一问题的核心有关。

源文件在编译后不会被使用

你可以对它进行
eval

use strict;
use warnings;

my $code = <<'__EOS__'
print "It works!!\n";
__EOS__

open(my $append_fh, ">>", "dynamic.pl")
   or die($!);
print($append_fh $code);
eval("$code; 1")
   or die($@);
使用严格;
使用警告;

my$code=源文件在编译后未被使用

你可以对它进行
eval

use strict;
use warnings;

my $code = <<'__EOS__'
print "It works!!\n";
__EOS__

open(my $append_fh, ">>", "dynamic.pl")
   or die($!);
print($append_fh $code);
eval("$code; 1")
   or die($@);
使用严格;
使用警告;

my$code=正如我在中提到的,您可以这样做,但这是一个重大的安全漏洞。你想用这个解决什么问题?也许有更好的解决办法。这不是为了什么特别的事,我只是好奇看看它是否能奏效。eval函数不是我想要的,因为我希望它不仅仅是执行print函数。我想,如果有人真的很聪明,他们可以用这样的方法来制作一个程序,随着时间的推移,它可以自我重新编程