如何基于字符串创建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的全局变量 我的项目使用

在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
的全局变量

我的项目使用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";