繁体   English   中英

将文件中的数据读入数组以在Perl脚本中进行操作

[英]Reading data from file into an array to manipulate within Perl script

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;

对于这个用例,哈希比数组好得多。

#!/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;

choroba的答案很理想,但我认为你自己的代码可以改进

  • 除非您需要仅在给定版本的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

我希望有所帮助

关于如何将数据存储在数组中的原始问题...

首先,在文件读取循环外初始化一个空数组:

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};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM