7

在 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";

产生:

变量“$bah”未在 /nfs/pdx/home/rbroger1/tmp2.pl 第 12 行导入。
全局符号“$bah”在 /nfs/pdx/home/rbroger1/tmp2.pl 第 12 行需要明确的包名称。
/nfs/pdx/home/rbroger1/tmp2.pl 的执行由于编译错误而中止。

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

4

6 回答 6

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 = \'测试';
$VAR2 = {
          'a' => 1,
          'b' => 2
        };
$VAR3 = [
          '一种',
          'b',
          'C'
        ];
于 2010-02-16T19:44:51.797 回答
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 的varspragma 会做你想做的事:

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');
于 2010-02-16T18:58:21.433 回答
2

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

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

编辑

刚刚验证您只能在没有myand 的情况下执行此操作no strict refs

于 2010-02-16T18:55:33.850 回答
2

试试看这个问题: Perl 有类似 PHP 的动态变量吗?

简而言之,您似乎应该能够做到$$glob_var_str = "whatever";

于 2010-02-16T18:57:50.073 回答
2

编译指示已经完成了你想要的vars繁重工作,所以让它发挥作用:

#! /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";

无论哪种方式,输出都是

废话

我很想知道你为什么要这样做,而不是用our. 是的,可能需要几次迭代才能全部捕获,但无论如何这些都是短期修复,对吧?

通常,您可以使用变量作为变量名(请参阅perlref 中的“符号引用”),但您真的、真的、真的不想这样做:启用strict 'refs'pragma 会禁用此功能。

Rafael Garcia-Suarez 在写道:“我不知道你原来的问题是什么,但我建议使用哈希。”时表现出极大的智慧。</p>

也可以看看:

于 2010-02-16T19:29:05.790 回答
1

Sinan Ünür 的回答确实是最好的。然而,这引起了我的好奇心,所以我做了一些阅读(perldoc perlmod)并了解了“package_name::”哈希作为访问包命名空间的一种方式。

以下代码在 main:: 包的符号表中添加一条记录:

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

print "$main::blah\n";

这将打印“sss”。

但是,我不得不在打印语句中添加包名,因为“使用严格”仍然没有被愚弄。我会继续寻找 - 使用 vars 目前似乎不起作用。

于 2010-02-22T01:29:21.767 回答