我有一个使用哈希的Perl脚本,其中的内容是UUID,键是XML文本元素。 XML文本元素使用普通排序合理地排序。
在处理每个元素时,我将其写入日志文件。相关代码如下:
use 5.016;
open(my $loghandle, '>', 'process.log') or die "Couldn't open logfile";
%XMLhash = (
'e01af02f-e8e5-476e-a250-e70c3925463a' => '<Form><AUni ws="fr">retirer</AUni></Form>',
'8187b534-a8c8-4e14-bf0b-1bd9cfada31e' => '<Form><AUni ws="fr">pencher</AUni></Form>',
'1848c7a2-c2f8-4884-8327-c0f1a9da7a4b' => '<Form><AUni ws="en">repair</AUni></Form>',
'b36c127c-91b2-41db-96ec-18c172ad9917' => '<Form><AUni ws="fr">fou</AUni></Form>',
'abb4e9dc-dc66-43b5-951e-e720e21da286' => '<Form><AUni ws="en">four</AUni></Form>',
'8cf707e6-e0a1-4611-bb28-ff18d2de38db' => '<Form><AUni ws="en">robust</AUni></Form>',
);
while( my( $guid, $XMLtext ) = each %XMLhash ) {
my $somestuff = 'What I did', # some process that tells what I did
say $loghandle "Text:$XMLtext Guid:$guid I did $somestuff";
}
及其生成的日志文件(每次运行的顺序可能不同):
Text:<Form><AUni ws="en">robust</AUni></Form> Guid:8cf707e6-e0a1-4611-bb28-ff18d2de38db I did:What I did
Text:<Form><AUni ws="en">four</AUni></Form> Guid:abb4e9dc-dc66-43b5-951e-e720e21da286 I did:What I did
Text:<Form><AUni ws="fr">retirer</AUni></Form> Guid:e01af02f-e8e5-476e-a250-e70c3925463a I did:What I did
Text:<Form><AUni ws="fr">fou</AUni></Form> Guid:b36c127c-91b2-41db-96ec-18c172ad9917 I did:What I did
Text:<Form><AUni ws="en">repair</AUni></Form> Guid:1848c7a2-c2f8-4884-8327-c0f1a9da7a4b I did:What I did
Text:<Form><AUni ws="fr">pencher</AUni></Form> Guid:8187b534-a8c8-4e14-bf0b-1bd9cfada31e I did:What I did
我希望日志文件按XML文本(即哈希键)排序。
我尝试将while语句更改为:
while( my( $guid, $XMLtext ) = each sort keys %XMLhash ) {
这给了我一个错误:“每个引用对象的参数类型必须是...处的无哈希值hashref或arrayref”。
要获得排序的日志文件,我可以按键顺序处理哈希吗?
在我当前的解决方法中,我将日志写入一个数组,对该数组进行排序,然后将该数组写入日志文件。在我看来,这不是最佳选择。
答案 0 :(得分:1)
请勿为此使用each
。它仅适用于散列(以及较新的Perls中的数组)。使用常规的foreach
并按值排序。
foreach my $key ( sort { $xml{$a} cmp $xml{$b} } keys %xml ) {
say "$key: $xml{$key}";
}
您需要获取键,然后对值进行排序,因为这就是XML东西所在的位置。
如果要先按文本节点排序,然后按ws
属性对单个文本节点进行排序,则会变得更加复杂。
foreach my $key ( map { $_->[0] }
sort { $a->[2] cmp $b->[2] || $a->[1] cmp $b->[1] }
map { [ $_, $xml{$_} =~ m/"(..)">([^<]+)</ ] } keys %xml
) {
say "$key: $xml{$key}";
}
这利用了所谓的Schwartzian transform,后者执行一次昂贵的操作,将要存储的结果存储在上面,然后将原始数据放回原处。由于您的XML代码段始终具有相同的格式,因此使用正则表达式提取要排序的数据会节省很多时间。