我在你的程序中做了一些修改:
#! /usr/bin/env perl
#
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
print "Scalar version: $Scalar::Util::VERSION\n";
what_the_fudge();
what_the_fudge();
what_the_fudge();
sub what_the_fudge {
my $string = "foo 123 bar";
if ($string =~ /foo (.+) bar/) {
if ( looks_like_number $1 ) {
print qq("$1" looks like a number\n);
} else {
print qq("$1" doesn't look like a number\n);
}
}
}
我有一台运行 10.8.6 的 Mac,我使用 Perlbrew 来测试 5.8.9、5.10、5.12 和 5.18。前两个我得到这个:
Scalar version: 1.19
"123" doesnt look like a number
"123" looks like a number
"123" looks like a number
对于其他两个版本,我得到了这个:
Scalar version: 1.22
"123" looks like a number
"123" looks like a number
"123" looks like a number
然后,我对您的程序进行了另一个细微的更改。我没有简单地使用$1
,而是设置my $test = $1
,然后运行looks_like_number( $test )
;
这样做之后,我得到了这个:
Scalar version: 1.19
"123" looks like a number
"123" looks like a number
"123" looks like a number
您必须了解的一件事是$1
,$_
和它们的同类不仅是全局变量,而且总是在main
命名空间中。这意味着如果您使用 调用子例程$1
,则子例程可能最终会修改该值。
您应该始终分配您自己的变量(最好my
是变量),而不是依赖特殊的 Perl 变量。这意味着不使用$_
inwhile
和for
循环,也不@_
直接在子例程中进行操作。而且,当您使用正则表达式捕获时,您应该尽快将自己的变量分配给$1
、$2
等。
顺便说一句,Scalar::Util 1.22 版和 1.19 版之间最有趣的区别是 1.22 版将使用 C 编译代码(如果存在)。如果没有,它会加载 Scalar::Util::PP 这是 Perl 版本。但是,当我Scalar::Util::PP
在 Perl 5.12 和 5.18 中使用时,我仍然得到正确的输出。
越来越好奇
我尝试修改Scalar::Util
以查看发生了什么。但是,我看到:
require List::Util; # List::Util loads the XS
Perl 版本的代码包含在一个大的 Eval 语句中。有趣的是,副作用只出现在第一个中——尽管子例程正在设置字符串并运行正则表达式。相同的代码,但执行两种不同的方式。
在周围添加引号$1
使其行为正确:
if ( looks_like_number "$1" ) {
也只需将其打印出来即可:
print "The value is " . $1 . "\n";
if ( looks_like_number $1 ) {
或将其分配给另一个变量,但不使用该变量:
my $test = $1;
if ( looks_like_number $1 ) { works now...
让我们使用调试器,看看我们是否可以跟踪问题:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.31
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:7): print "Version of Scalar::Util: $Scalar::Util::VERSION\n";
DB<1> c
Version of Scalar::Util: 1.19
"123" looks like a number.
"123" looks like a number.
"123" looks like a number.
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
有用?-d
让我们尝试不带参数的相同命令:
$ perl test.pl
Version of Scalar::Util: 1.19
"123" doesn't look like a number.
"123" looks like a number.
"123" looks like a number.
如果在调试器中看不到这个问题,你怎么能找到它?