在Perl中,是否可以基于字符串创建全局变量?
,例如,如果我有这样的功能:
sub create_glob_var {
my ($glob_var_str) = @_;
# something like this ( but not a hash access).
our ${$glob_var_str};
};
我称之为:
create_glob_var( "bar" );
如何修改create_glob_var
以实际创建名为$bar
的全局变量?
我的项目使用的是perl 5.8.5。
修改
以下不起作用:
use strict;
BEGIN {
sub create_glob_var {
my ($glob_var_str) = @_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
create_glob_var("bah");
};
$bah = "blah";
产地:
Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12. Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12. Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.
注意我意识到使用全局变量导致ozone depletion and male pattern baldness。我正在尝试清理一些已经完全被全局变量感染的遗留代码。一次只有一个重构......
答案 0 :(得分:5)
如果您要清理旧代码,可以编写一个导出所需变量的模块。每当您觉得需要调用create_glob_var
时,请将此变量添加到此包并将其放入导入列表中。
这将帮助您跟踪正在发生的事情以及变量的使用方式。
package MyVars;
use strict; use warnings;
use Exporter 'import';
our($x, %y, @z);
our @EXPORT_OK = qw( $x %y @z );
剧本:
#!/usr/bin/perl
use strict;use warnings;
use MyVars qw( $x %y @z );
$x = 'test';
%y = (a => 1, b => 2);
@z = qw( a b c);
use Data::Dumper;
print Dumper \($x, %y, @z);
输出:
$VAR1 = \'test'; $VAR2 = { 'a' => 1, 'b' => 2 }; $VAR3 = [ 'a', 'b', 'c' ];
答案 1 :(得分:3)
sub create_glob_var {
my ($glob_var_str) = @_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
no strict 'refs'
仅在use strict
生效时才有必要,它始终应该是。
附录:
如果您正在询问是否有办法编写子程序create_glob_var
,以便以下代码成功:
use strict;
create_glob_var("bar");
$bar = "whatever";
...然后答案是“不”但是,Perl的vars
编译指示将执行您想要的操作:
use strict;
use vars qw($bar);
$bar = "whatever";
但这是一种旧式的Perl编码。如今,人们通常会这样做:
use strict;
our $bar = "blah";
our
也可以声明可以在以后自由使用的全局变量:
our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');
答案 2 :(得分:2)
你必须使用eval
,但这通常被认为是邪恶的。类似的东西:
eval("$glob_var_str = \@_;");
修改的
只是确认您只能在没有my
和no strict refs
的情况下执行此操作。
答案 3 :(得分:2)
试着看看这个问题: Does Perl have PHP-like dynamic variables?
简而言之,您似乎应该能够$$glob_var_str = "whatever";
答案 4 :(得分:2)
vars
pragma已经为你想要的东西做了很多工作,所以把它付诸实践:
#! /usr/bin/perl
use warnings;
use strict;
use vars;
BEGIN { vars->import(qw/ $bah /) }
$bah = "blah";
print $bah, "\n";
如果您想拼写create_glob_var
,请使用
#! /usr/bin/perl
use warnings;
use strict;
use vars;
sub create_glob_var { vars->import("\$$_[0]") }
BEGIN { create_glob_var "bah" }
$bah = "blah";
print $bah, "\n";
无论哪种方式,输出都是
blah
我很想知道你为什么要这样做而不是用our
声明这些变量。是的,可能需要几次迭代才能抓住它们,但这些都是短期修复,对吧?
通常,您可以将变量用作变量名称(请参阅"Symbolic references" in perlref),但您确实真的 不希望这样做:启用{{ 1}} pragma禁用此功能。
Rafael Garcia-Suarez写道:“我不知道你原来的问题是什么,但我建议使用哈希。”
另见:
答案 5 :(得分:1)
SinanÜnür的回答确实是最好的。然而,这引起了我的好奇心,所以我做了一些阅读(perldoc perlmod)并学习了“package_name ::”hash作为访问包名称空间的方法。
以下代码将记录添加到main :: package的符号表中:
use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;
print "$main::blah\n";
这会打印“sss”。
但是,我不得不将包名添加到print语句中,因为“use strict”仍然没有被愚弄。我会继续寻找 - 目前使用vars似乎不起作用。