perl - 在 Perl 中解析具有重复部分的文件

标签 perl parsing hash

我正在尝试使用 Perl 来解析具有如下重复部分的文件:

System:      server1.domain.com
Start Time:  20121021T01:00:56
Stop Time:   20121021T01:00:56
Return Code: 0

Output
------
user1
user2
user3

##############################

System:      server2.domain.com
Start Time:  20121021T01:00:56
Stop Time:   20121021T01:00:56
Return Code: 0

Output
------
user1
user4
user5
user6

我可以将输入记录分隔符设置为“################################”,这会给我每个 block 作为一个单独的记录。

但我需要能够使用用户名作为每个服务器的 key 来填充哈希。

实现这一目标的最佳方法是什么?

最佳答案

您应该查看Perl references .

在 Perl 预发行版 5.0 中,您拥有三种类型的数据结构,并且只能在其中存储标量数据。例如,我可以有一个哈希值,但哈希值的每个值都可以是字符串或数字。

Perl 5.0 引入了引用资料。引用是指向另一个数据结构的一段数据。例如,您可以有一个代表服务器的哈希值。散列的每个成员都指向另一个包含用户的散列(如果您愿意,也可以是用户列表)。

例如,您有一个如下所示的哈希:

$system{server1.domain.com}  --->  $anon_array[0] = "user1"
                                   $anon_array[1] = "user2"
                                   $anon_array[2] = "user3"

$system{server2.domain.com}  ----> $another_anon_array[0] = "user1"
                                   $another_anon_array[1] = "user2"
                                   $another_anon_array[2] = "user3"
                                   $another_anon_array[3] = "user4"

您可以在上面看到您的 %system 的 key hash 实际上指向内存中包含用户列表的某个数组。这些数组没有名称,例如 @foo@bar 。您访问它们的唯一方法是通过您的 %system哈希。因此,它们被称为匿名数组。

要创建引用,请在变量前面放置一个反斜杠:

$my_reference = \%my_hash

现在,$my_reference指向哈希 %my_hash成员 。如果我想再次将引用转换为哈希值,我可以在其前面添加哈希符号( % ):

%bar = %{$my_reference};

您可以使用->显示某物指向引用的语法:

$foo->[0];   Points to the first member of an anonymous array.

$bar = [];    #Sets $bar to be a reference to an anonymous array
$foo = {};    #Sets $foo to be a reference to an anonymous hash.

现在,真正的乐趣可以开始了!您现在可以存储整个数据结构,而不是存储单个值。

想象一下这样的事情:

my %system;   #Normal hash keyed by domain name

$system{server1} = {};  # This points to an anonymous hash!
$system{server1}->{START}  = "20121021T01:00:56";
$system{server1}->{STOP}   = "20121021T01:00:56";
$system{server1}->{RETURN} = 0;
$system{server1}->{USERS} = [];  #This hash entry points to an anonymous array
$system{server1}->{USERS}->[0] = "user1";
$system{server1}->{USERS}->[1] = "user2";
$system{server1}->{USERS}->[2] = "user3";

依此类推 server2 。您有一个哈希 %system由域名作为键控。您 %system 中的每个域哈希有一个 START时间STOP时间,一个RETURN值,一个 USERS 的列表在那个系统上。 server1 的开始时间是几点? ?这是$system{server1}->{START}system2上的用户列表是什么? ?这是@{ $system{server2}->{USERS} } (对存储在 $system{server2}->{USERS} 中的数组的取消引用)。

需要一些时间来适应这种新的思维方式,但您可以看到它有助于将数据保持为单一结构。

当然,复杂的数据结构会带来保持其正确性的问题。例如:

use strict;
use warnings;

my %server;
$servre{domain1} = "10.10.1.20";

会失败,因为我从未声明 $servre 。但是:

use strict;
use warnings;
my $hash = {};
$hash->{SERVRE}->{domain1} = "10.10.1.20";

会工作得很好。在这种情况下,SERVRE是哈希引用的键,而不是变量。 use strict;在这种情况下,pragma 不会检测到我的错误拼写。这将引导您进入下一步:面向对象的 Perl。然而,首先要了解这些新的复杂数据结构及其工作原理。当您在程序中更习惯地使用它们之后,您可以开始研究面向对象编程将如何帮助解决它们造成的困惑。

关于perl - 在 Perl 中解析具有重复部分的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13022055/

相关文章:

mysql - Redis 排序 : How do I sort a redis hash key by given value?

regex - 解析 StarTeam 命令行客户端输出

linux - 比较和显示哈希值

java - 如何从ajax网页获取所有文本内容

xml - 使用自定义标签解析多个 XML 文件

parsing - 如何从 SCADA CIMPLICITY 软件的 DAT 和 IDX 文件中提取数据?

python - HMAC签名和直接散列有什么区别?

javascript - 页面完全写入后,从 cgi 重定向到 html

perl - glob 无法识别带方括号的文件名

hash - Docker层信息发布v1.10