阅读参考资料。此外,阅读现代 Perl 实践,这将有助于提高您的编程技能。
您可以将信息存储在这些哈希中,而不仅仅是使用唯一 URL 哈希的键。让我们从唯一 URL 的计数开始:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use feature qw(say);
use constant {
WEB_FILE => "web1.txt",
};
open my $web_fh, "<", WEBFILE; #Autodie will catch this for you
my %unique_urls;
while ( my $line = <$web_fh> ) {
my $url = (split /\s+/, $line)[9];
if ( not exists $unique_urls{$url} ) { #Not really needed
$unique_urls{$url} = 0;
}
$unique_urls{$url} += 1;
}
close $web_fh;
现在,您的 %unique_urls 哈希中的每个键都将包含您拥有的唯一 URL 的数量。
顺便说一句,这是您的代码以更现代的风格编写的。use strict;
和pragma将捕获大约 90% 的标准编程错误。将捕获您忘记检查的事物的异常。在这种情况下,如果文件不存在,程序将自动终止。use warnings;
use autodie;
该open
命令的三参数版本是首选,文件句柄使用标量变量也是如此。为文件句柄使用标量变量使它们更容易在子例程中传递,并且如果文件句柄超出范围,文件将自动关闭。
但是,我们希望每个哈希存储两个项目。我们想要存储唯一计数,并且我们想要存储一些可以帮助我们找到平均响应时间的东西。这就是引用的来源。
在 Perl 中,变量处理单个数据项。标量变量(如$foo
)处理单个数据项。数组和散列(如@foo
和%foo
)处理单个数据项的列表。参考资料可帮助您绕过此限制。
我们来看一组人:
$person[0] = "Bob";
$person[1] = "Ted";
$person[2] = "Carol";
$person[3] = "Alice";
然而,人不仅仅是名字。他们有姓氏、电话号码、地址等。让我们看一下 Bob 的哈希:
my %bob_hash;
$bob_hash{FIRST_NAME} = "Bob";
$bob_hash{LAST_NAME} = "Jones";
$bob_hash{PHONE} = "555-1234";
我们可以通过在它前面放一个反斜杠来引用这个哈希。引用只是存储此哈希的内存地址:
$bob_reference = \%bob_hash;
print "$bob_reference\n": # Prints out something like HASH(0x7fbf79004140)
但是,该内存地址是一个单独的项目,并且可以存储在我们的人员数组中!
$person[0] = $bob_reference;
如果我们想访问引用中的项目,我们通过将正确的数据类型符号放在前面来取消引用它。由于这是一个哈希,我们将使用%
:
$bob_hash = %{ $person[0] };
->
Perl 提供了一种使用以下语法取消引用哈希的简单方法:
$person[0]->{FIRST_NAME} = "Bob";
$person[0]->{LAST_NAME} = "Jones";
$person[0]->{PHONE} = "555-1212";
我们将使用相同的技术%unique_urls
来存储次数和响应时间的总量。(平均值为总时间/次数)。
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use feature qw(say);
use constant {
WEB_FILE => "web1.txt",
};
open my $web_fh, "<", WEB_FILE; #Autodie will catch this for you
my %unique_urls;
while ( my $line ( <$web_fh> ) {
my $url = (split /\s+/, $line)[9];
my $response_time = (split /\s+/, $line)[10]; #Taking a guess
if ( not exists $unique_urls{$url} ) { #Not really needed
$unique_urls{$url}->{INSTANCES} = 0;
$unique_urls{$url}->{TOTAL_RESP_TIME} = 0;
}
$unique_urls{$url}->{INSTANCES} += 1;
$unique_urls{$url}->{TOTAL_RESP_TIME} += $response_time;
}
$close $web_fh;
现在我们可以将它们打印出来:
print "%20.20s %6s %8s\n", "URL", "INST", "AVE";
for my $url ( sort keys %unique_urls ) {
my $total_resp_time = $unique_urls{$url}->{TOTAL_RESP_TIME};
my $instances = $unique_urls{$url}->{INSTANCES};
my $average = $total_resp_time / $instances
printf "%-20.20s %-6d %-8.5f\n", $url, $instances, $average";
}
我喜欢用printf
在桌子上。