首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl -模式匹配中未初始化值$_的使用

Perl -模式匹配中未初始化值$_的使用
EN

Stack Overflow用户
提问于 2015-04-30 13:56:17
回答 4查看 3K关注 0票数 1

我在弄清楚如何在我的perl脚本中抑制/纠正导致警告"Use of uninitialized value $_ in pattern match"的原因时遇到了一些困难。

下面是生成警告的单元测试脚本

Interview.t

代码语言:javascript
复制
#!/usr/bin/perl

use warnings;
use strict;
use Test::More tests => 16;
use v5.10;
use Data::Dumper;

require_ok('Interview');

# Test URLs
my $test_urls = {
    'http://www.reddit.com'  => 1,
    'hurrdurrimasheep'       => 0
};

my $interview = new Interview;

# Test $interview to see if it's an instance of our 'Interview' class
isa_ok($interview, 'Interview');

# Test to see if $interview has the member functions 'a' and 'b'
can_ok($interview, qw/a b/);

eval { $interview->a; };

cmp_ok($@, '=~', /Oh boy, thats blown to bits/, 'Interview->a dies as expected when no url argument is given.');

eval { $interview->b; };

cmp_ok($@, '=~', /Rubbish/, "Interview->b dies as expected when there are no results in Interview->{'r'}");

# Test to see if the return value from $interview's 'a' member function 
# will either be '1' or '0'.
foreach my $url (keys $test_urls) {
    cmp_ok($interview->a($url), 'eq', $test_urls->{$url}, "Got expected result for Interview->a($url): [ $test_urls->{$url} ]");
}

open(STDOUT, ">/dev/null") || die "Can't redirect stdout";
my $interview_url_results = $interview->b;
close(STDOUT);

my $num_test_urls      = keys scalar $test_urls;
my $num_interview_urls = keys scalar $interview_url_results;

cmp_ok($num_test_urls, '==', $num_interview_urls, "Got expected number of urls returned from Interview->b(): [ $num_test_urls ]");

# The following test ensures that the Interview->b() member function
# is storing the codes returned from Interview->a() correctly.

foreach my $url (keys $interview_url_results) {
    my $expected_code = $test_urls->{$url};
    my $returned_code = $interview->{'r'}->{$url};

    cmp_ok($expected_code, '==', ($returned_code == 200 ? 1 : 0), "Got expected http code from Interview->b() for $url");
}

done_testing;

Interview.pm

代码语言:javascript
复制
package Interview;

use strict;
use warnings;

sub new {
    my $c = shift;

    return bless {}, $c;
}

sub a {
    my ($self, $u) = @_;
    die 'Oh boy, thats blown to bits' if ! $u;

    my $c = "curl -sL -w '%{http_code} %{url_effective}' '$u' -o /dev/null";
    `$c` =~ /^(\d+)\s/;
    $self->{'r'}->{$u} = $1;

    return $self->{'r'}->{$u} == 200 ? 1 : 0;
}

sub b {
    my $self = shift;
    die 'Rubbish' if ! $self->{'r'};

    foreach my $u (keys %{$self->{'r'}}) {
       print "Results: $u -- $self->{'r'}->{$u}\n";
    }
    return $self->{'r'};
}

1;

输出:

代码语言:javascript
复制
[  ¯\_(ツ)_/¯ ~/Development/Interview ]: perl Interview.t
1..10
ok 1 - require Interview;
ok 2 - The object isa Interview
ok 3 - Interview->can(...)
Use of uninitialized value $_ in pattern match (m//) at Interview.t line 27.
ok 4 - Interview->a dies as expected when no url argument is given.
Use of uninitialized value $_ in pattern match (m//) at Interview.t line 31.
ok 5 - Interview->b dies as expected when there are no results in Interview->{'r'}
ok 6 - Got expected result for Interview->a(hurrdurrimasheep): [ 0 ]
ok 7 - Got expected result for Interview->a(http://www.reddit.com): [ 1 ]
ok 8 - Got expected number of urls returned from Interview->b(): [ 2 ]
ok 9 - Got expected http code from Interview->b() for hurrdurrimasheep
ok 10 - Got expected http code from Interview->b() for http://www.reddit.com

你可以在测试3和4之后看到警告。我在这里漏掉了什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-04-30 14:02:40

警告来自以下一行:

代码语言:javascript
复制
cmp_ok($@, '=~', /Oh boy, thats blown to bits/, ...);

您希望将regex模式传递给cmp_ok,但需要传递一个值,指示$_是否包含Oh boy, thats blown to bits。警告来自这样一个事实:您从未向$_分配任何东西。但真正的问题是你应该用

代码语言:javascript
复制
cmp_ok($@, '=~', qr/Oh boy, thats blown to bits/, ...);

但这仍存在第二个问题。当没有异常发生时,$@将是undef,因此cmp_ok将在检查模式是否针对$@时发出警告。在这种情况下,like不仅更简单,而且它没有警告地处理undef

代码语言:javascript
复制
like($@, qr/Oh boy, thats blown to bits/, ...);
票数 6
EN

Stack Overflow用户

发布于 2015-04-30 14:05:52

就像@ikegami指出的,这句话是:

代码语言:javascript
复制
cmp_ok($@, '=~', /Oh boy, thats blown to bits/);

实际上应该是:

代码语言:javascript
复制
cmp_ok($@, '=~', qr/Oh boy, thats blown to bits/);

因为qr/xxx/是正则标量,但是/xxx/实际上根据$_计算正则表达式。

然而,更好的解决方案是使用like()函数而不是cmp_ok()

代码语言:javascript
复制
like($@, qr/Oh boy, thats blown to bits/);
票数 5
EN

Stack Overflow用户

发布于 2015-04-30 14:00:44

第27行是:

代码语言:javascript
复制
cmp_ok($@, '=~', /Oh boy, thats blown to bits/, 'Interview->a dies as expected when no url argument is given.');

那么,现在$@中有什么呢?我猜- eval { $interview->a; };回来了。因此,您可能需要首先测试它是否是defined

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29969709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档