Perl新手。我需要弄清楚如何从(:)分隔的文件中读取数组。然后我可以操纵数据。
以下是'serverFile.txt'文件的示例(只是随机扔了#) 这些字段是名称:CPU利用率:avgMemory用法:无磁盘
Server1:8:6:2225410
Server2:75:68:64392
Server3:95:90:12806
Server4:14:7:1548700
我想弄清楚如何将每个字段放入适当的数组然后执行函数。例如,找到具有最少可用磁盘空间的服务器。
我现在设置它的方式,我认为不会起作用。那么如何将每行中的每个元素放入一个数组中呢?
#!usr/bin/perl
use warnings;
use diagnostics;
use v5.26.1;
#Opens serverFile.txt or reports and error
open (my $fh, "<", "/root//Perl/serverFile.txt")
or die "System cannot find the file specified. $!";
#Prints out the details of the file format
sub header(){
print "Server ** CPU Util% ** Avg Mem Usage ** Free Disk\n";
print "-------------------------------------------------\n";
}
# Creates our variables
my ($name, $cpuUtil, $avgMemUsage, $diskFree);
my $count = 0;
my $totalMem = 0;
header();
# Loops through the program looking to see if CPU Utilization is greater than 90%
# If it is, it will print out the Server details
while(<$fh>) {
# Puts the file contents into the variables
($name, $cpuUtil, $avgMemUsage, $diskFree) = split(":", $_);
print "$name ** $cpuUtil% ** $avgMemUsage% ** $diskFree% ", "\n\n", if $cpuUtil > 90;
$totalMem = $avgMemUsage + $totalMem;
$count++;
}
print "The average memory usage for all servers is: ", $totalMem / $count. "%\n";
# Closes the file
close $fh;
答案 0 :(得分:5)
对于这个用例,哈希比数组要好得多。
#!/usr/bin/perl
use strict;
use feature qw{ say };
use warnings;
use List::Util qw{ min };
my %server;
while (<>) {
chomp;
my ($name, $cpu_utilization, $avg_memory, $disk_free)
= split /:/;
@{ $server{$name} }{qw{ cpu_utilization avg_memory disk_free }}
= ($cpu_utilization, $avg_memory, $disk_free);
}
my $least_disk = min(map $server{$_}{disk_free}, keys %server);
say for grep $server{$_}{disk_free} == $least_disk, keys %server;
答案 1 :(得分:4)
choroba's answer 是理想的,但我认为你自己的代码可以改进
除非您需要仅在给定版本的Perl中可用的特定功能,否则不要use v5.26.1
。请注意,它还启用use strict
,它应该位于您编写的每个Perl程序的顶部
die "System cannot find the file specified. $!"
错误:open
可能失败的原因有多种,除此之外“无法找到”。您的die
字符串应包含您尝试打开的文件的路径;失败的原因在于$!
不要使用子程序原型:它们不会按照您的想法执行。 sub header() { ... }
应该只是sub header { ... }
声明一个子程序只是稍后调用几行是没有意义的。将header
的代码放入行
你显然来自另一种语言。尽可能晚地使用my
声明变量。在这种情况下,必须在$count
循环之外声明$totalMem
和while
perl将在程序退出时关闭所有打开的文件句柄。很少需要明确的close
调用,这会让您的代码更加嘈杂
$totalMem = $avgMemUsage + $totalMem
通常是$totalMem += $avgMemUsage
我希望有帮助
答案 2 :(得分:-1)
关于如何将数据存储在数组中的原始问题......
首先,在文件读取循环外初始化一个空数组:
my @servers = ();
然后,在循环中,在解析完数据后,可以将它们作为子数组存储在数组中(结果数据结构是二维数组):
$servers[$count] = [ $name, $cpuUtil, $avgMemUsage, $diskFree ];
注意,右侧的方括号为服务器的数据块创建子数组,并返回对此新数组的引用。此外,在左侧,我们只使用 $ count 的当前值作为 @servers 数组中的索引,随着值的增加,的大小@servers 数组将自动增长(这称为新元素的自动生成)。或者,您可以将新元素推送到循环内的 @servers 数组中,如下所示:
push @servers, [ $name, $cpuUtil, $avgMemUsage, $diskFree ];
这样,您明确要求将新元素添加到数组中,方括号仍然执行相同的子数组创建。
在任何情况下,最终结果是在完成文件读取循环后,您现在有一个2D数组,您可以在其中访问第一个服务器及其无磁盘字段(索引3处的第4个字段)像这样:
my $df = $servers[0][3];
或者检查循环中的所有服务器以找到最小的可用磁盘:
my $min_s = 0;
for ( my $s = 0; $s < @servers; $s++ ) {
$min_s = $s if ( $servers[$s][3] < $servers[$min_s][3] );
}
print "Server $min_s has least disk free: $servers[$min_s][3]\n";
与@choroba建议一样,您可以将服务器数据片段/字段存储在哈希中,以便您的代码更具可读性。您仍然可以将您的服务器列表存储在一个数组中,但第二个维度可以是哈希:
$servers[$count] = {
name => $name,
cpu_util => $cpuUtil,
avg_mem_usage => $avgMemUsage,
disk_free => $diskFree
};
因此,您生成的结构将是一个哈希数组。这里,右边的花括号创建一个新的哈希并返回对它的引用。所以,您可以稍后参考:
my $df = $servers[0]{disk_free};