如何基于字符串创建Perl变量名?
在Perl中,是否可以基于字符串创建全局变量 例如,如果我有如下函数:如何基于字符串创建Perl变量名?,perl,symbolic-references,Perl,Symbolic References,在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\u glob\u var以实际创建名为$bar的全局变量 我的项目使用
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\u glob\u 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.
变量“$bah”未在/nfs/pdx/home/rbroger1/tmp2.pl第12行导入。
全局符号“$bah”要求在/nfs/pdx/home/rbroger1/tmp2.pl第12行显示包名。
由于编译错误,/nfs/pdx/home/rbroger1/tmp2.pl的执行被中止。
注意我意识到使用全局变量会导致。我试图清理一些已经完全受全局变量影响的遗留代码。每次重构一次…您必须使用
评估,但这通常被认为是邪恶的。比如:
eval($glob\u var\u str=\@代码>
编辑
刚才验证了您只能在没有my
和无严格参考的情况下执行此操作
尝试查看以下问题:
简而言之,您似乎应该能够执行$$glob\u var\u str=“whatever”代码>
只有当使用严格的
有效时,才需要无严格的“参考”
,而这应该始终有效
增编:
如果您询问是否有方法编写子例程create\u glob\u var
,以使以下代码成功:
use strict;
create_glob_var("bar");
$bar = "whatever";
…然后答案是“否”。然而,Perl的vars
pragma将执行您想要的操作:
use strict;
use vars qw($bar);
$bar = "whatever";
但这是一种老式的Perl编码。如今,人们通常会这样做:
use strict;
our $bar = "blah";
我们的
也可以声明全局变量,以后可以自由使用:
our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');
pragma已经为您的需求完成了繁重的工作,因此请将其付诸实施:
#! /usr/bin/perl
use warnings;
use strict;
use vars;
BEGIN { vars->import(qw/ $bah /) }
$bah = "blah";
print $bah, "\n";
如果您喜欢拼写它create\u glob\u 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
废话
我很想知道为什么要这样做,而不是用声明这些变量。是的,可能需要几次迭代才能全部解决,但这些都是短期修复,对吗
一般来说,您可以使用变量作为变量名(请参见),但您真的、真的、真的不想这样做:启用strict'refs'
pragma将禁用此功能
拉斐尔·加西亚·苏亚雷斯(Rafael Garcia Suarez)写道:“我不知道你最初的问题是什么,但我建议使用散列。”
另见:
如果您试图清理旧代码,可以编写一个模块来导出所需的变量。每当您觉得需要调用create\u glob\u 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'
];
$VAR1=\'test';
$VAR2={
“a”=>1,
“b”=>2
};
$VAR3=[
“a”,
“b”,
“c”
]; 西南努尔的答案确实是最好的。然而,这激发了我的好奇心,所以我读了一些书(perldoc perlmod),了解了“package_name::”散列作为访问包名称空间的一种方式
以下代码将记录添加到main::package的符号表中:
use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;
print "$main::blah\n";
这个打印“sss”
然而,我不得不在print语句中添加包名,因为“use strict”仍然没有被愚弄。我会继续寻找-使用变量目前似乎不起作用。使用使用严格的或不使用?eval可以做到,但有多种方法可以做到。。。你不必使用eval。如果你没有使用使用strict
,你不需要无严格
任何东西。不过,你应该先在块中使用无严格引用
。(因为你应该严格遵守!)谢谢你的回答。它似乎不起作用<代码>严格
在编译时抱怨。请参阅我更新的帖子。子例程创建了全局变量,但您仍然需要以strict可以接受的方式访问它,可能是1)$my::Package::bah=“blah”,2)使用vars qw($bah)$我们的$bah=“blah”,或3)我们的$bah=“blah”。不要做这样的事情。见“同意”。使用全局散列来存储数据(如果您必须使用全局变量),而不是创建新的标量!我之所以要做这些事情,是因为有人通过创建自定义命令行解析器来重新发明轮子。它贯穿于我们所有的工具堆栈。不幸的是,当前声明选项的方法涉及修改跨越3000行代码的3段代码。这真的很可怕,而且严重违反了D.R.Y.我试图通过某种方式将创建新选项所需的所有代码收集到不到10行的连续代码中,从而减少在整个代码库中重复自己的需要。
use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;
print "$main::blah\n";