如何检查变量是否在perl中声明?

jgwigjjp  于 2023-03-09  发布在  Perl
关注(0)|答案(9)|浏览(186)

我在perl中使用use strict;,并使用下面的语句。

unless(defined($x)){
      print "Not defined";
}

其中$x没有在任何地方声明。所以我希望它打印“Not defined“,但是它返回了一个错误

Global symbol "$x" requires explicit package name at *********** in line 15.
yfwxisqw

yfwxisqw1#

strict pragma由三部分组成:严格引用、严格变量和严格子函数。您遇到的是

严格变量

如果你访问的变量不是通过ouruse vars声明的,或者不是通过my本地化的,或者不是完全限定的,那么就会产生编译时错误,因为这是为了避免变量自杀问题和微妙的动态作用域问题,仅仅使用local变量是不够的。
因为它会产生编译时错误,所以你的非BEGIN代码甚至没有机会运行。

{
  no strict 'vars';
  print "Not defined!\n" unless defined $x;
}

但请注意,Perl的defined操作符告诉您是否定义了值,而不是是否声明了变量。
告诉我们更多关于您的申请,我们可以给予你更好的建议,如何处理它。

vltsax25

vltsax252#

你甚至不能引用一个变量,除非它被声明了。

defined( $x ) ?

编译器会抱怨:我不知道你问的是什么,我怎么知道它是定义好的,它没有变量的引用点,因为你已经指出你不希望变量是自动创建的。
如果strict 'vars'没有打开--当您使用use strict时,默认情况下是打开的--那么它将在包符号表中为'x'创建一个条目。
有趣的是,如果没有strict 'refs',检查变量是否在包符号表中也很容易。

defined( *{ __PACKAGE__ . '::x' }{SCALAR} )

因为没有办法自动创建词法变量(“my variables”),所以也没有标准的方法来检查词法变量是否被声明。词法变量存储在“pad”中。但是有一个模块PadWalker可以提供帮助。
为了检查当前的层级,你可以得到一个pad的哈希值,然后检查它是否存在于当前的pad中,你也可以在堆栈中向上循环(integer参数的工作原理类似于caller),找到最近的x在哪里。

my $h = peek_my (0);
exists $h->{x};
tuwxkamq

tuwxkamq3#

我认为您混淆了“已定义”和“已声明”的概念。
你问的是“如何检查变量是否在perl中声明”,但你检查的是变量是否被定义了。这是两个不同的概念。
在perl中,如果你使用 'use strict',你会自动检查任何没有声明的变量(使用mylocalour)。一旦你声明了一个变量,你就可以测试它是否被定义(赋值)。
因此,在测试中,您在测试定义性之前缺少了一个先前的声明

use strict;
my $x;  # you are missing this part
[...] | # code
# your test for define
print defined $x? "defined\n" : "not defined\n";

请注意,仅针对$x的测试不符合您的目的:

my ($x,$y, $z);
$w;         # not declared (use strict will catch it and die)
$x = 0;     # declared and defined BUT if you make a logic test like 'if ($x) {}' then it will be FALSE, so don't confuse testing for **'$x'** and testing for **'defined $x'**
$y = undef; # declared but not defined
$z = 1;     # declared, defined, and logial test TRUE

最后,我认为,关于杀鼠剂的回答是错误的:他建议使用**“除非$x”,如果按照我前面所说定义,那么这对于测试是不正确的。他还建议使用**“除非存在$x”,这对于测试标量是错误的。“存在”测试只针对散列键(不赞成用于数组)。
希望这个有用。

fcwjkofz

fcwjkofz4#

#
 print "Not defined" if !defined($x);

结果将是
未定义

#
 use strict;
 print "Not defined" if !defined($x);

会产生你问题中的错误。
请看:http://perldoc.perl.org/strict.html,其中描述了如何只导入所需的限制。(但是使用严格的"vars"是非常好的主意:))

r55awzrz

r55awzrz5#

通常这种代码不应该是一个严肃的程序所必需的,但为什么不只是为了好玩呢?(假设使用strict)

print "Not defined\n" unless eval 'ref(\$x)';
bqujaahr

bqujaahr6#

看起来你可以像这样检查变量是否被声明(如man perlmod中的“符号表”所述):

main::(-e:1):   1
  DB<1> x __PACKAGE__
0  'main'
  DB<2> x exists ${__PACKAGE__ . '::'}{xyz}
0  ''
  DB<3> $xyz = undef
  DB<4> x exists ${__PACKAGE__ . '::'}{xyz}
0  1
  DB<5> $xyz = 7
  DB<6> x exists ${__PACKAGE__ . '::'}{xyz}
0  1

所以在perl -d -e 1之后,你在包main中,$xyz没有被声明。因此(“全局”)xyz不存在于main的符号表中。但是在将undef赋给一个同名变量之后,符号表中有一个条目。
这种机制仍然不适用于my变量(词法范围)。

ccrfmcuu

ccrfmcuu7#

#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;
gz5pxeao

gz5pxeao8#

我的解决方案是#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;
ntjbwcob

ntjbwcob9#

您可以使用unless,如下所示:

use 'strict';

my $var = 'defined';
unless (defined($var)) {
  print "not defined\n";
}

$var = undef;
unless (defined($var)) {
  print "not defined\n";
}

第一个print将不打印任何内容,第二个将打印任何内容,因为$var已变为undef

相关问题