我正在尝试使用 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/