在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.

笔记 我意识到使用全局变量会导致 臭氧消耗与男性型秃发. 。我正在尝试清理一些已经完全被全局变量的使用所感染的遗留代码。一次重构一个......

有帮助吗?

解决方案

如果你想清理旧代码,你可以写一个出口所需的变量(一个或多个)的模块。每当你觉得有必要援引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'
        ];

其他提示

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');

试着看一下这个问题: 是否Perl的具有PHP状动态变量?

在简单地说,好像你应该能够做到$$glob_var_str = "whatever";

您将不得不使用eval,但是这通常被认为是邪恶的。是这样的:

eval("$glob_var_str = \@_;");

修改

只是验证,你只能这样做没有myno strict refs

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. 。是的,可能需要几次迭代才能捕获所有这些,但无论如何这些都是短期修复,对吗?

一般来说,您可以使用变量作为变量名(请参见 perlref 中的“符号引用”),但你真的真的, 真的 不想这样做:启用 strict 'refs' pragma 禁用此功能。

拉斐尔·加西亚-苏亚雷斯(Rafael Garcia-Suarez)在写道“我不知道你最初的问题是什么,但我建议使用哈希”时表现出了极大的智慧。

也可以看看:

由思南Ünür回答确实是最好的。但是,这种回升我的好奇心,所以我做的读取(参阅perldoc perlmod的)一点,学会了“PACKAGE_NAME ::”哈希值,以此来访问一个包的命名空间。

下面的代码将记录添加到主::包的符号表中:

use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;

print "$main::blah\n";

此打印 “SSS”。

不过,我不得不包名称添加到打印语句,因为“使用严格”依然没有上当。我将继续寻找 - 使用增值经销商似乎并不在目前的工作

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top