функция ключей в perl

У меня есть perl-скрипт, который оценивает xml-скрипт с помощью функции keys(). Мой скрипт написан таким образом, атрибуты/теги в xml идут не по порядку. Работают ли ключи в Perl, оцениваются случайным образом??

Ex:

if( (keys %{$data})[0] eq 'fileFooter' and
    (keys %{$data->{fileFooter}})[0] eq 'measCollec' and
    (keys %{$data->{fileFooter}->{measCollec}})[0] eq 'endTime' and
    (keys %{$data})[1] eq 'fileHeader' and
    (keys %{$data->{fileHeader}})[0] eq 'measCollec' and
    (keys %{$data->{fileHeader}->{measCollec}})[0] eq 'beginTime'

Здесь атрибут fileFooter в файле XML находится в конце, а fileHEader — в начале. В этом случае perl будет работать нормально??

Пожалуйста, найдите сценарий по ссылке ниже: https://docs.zoho.com/writer/published.do?rid=x6jdb8effa7ba9b0140258c9b3b1fb9617386

Пожалуйста, найдите файл XML по ссылке ниже:

https://docs.zoho.com/writer/ropen.do?rid=x6jdbcd99dd2df097455f99fa2907a84620ee


person Amar    schedule 15.06.2015    source источник
comment
Хэши Perl неупорядочены. Вы не можете полагаться на хэш для возврата ключей в каком-либо конкретном порядке.   -  person friedo    schedule 15.06.2015
comment
Это также выглядит как XML, проанализированный XML::Simple. Я бы предложил использовать что-то другое, а вместо этого просто использовать выражения xpath. Приведите образец XML и желаемый результат, и я уверен, что кто-нибудь может привести вам работающий пример.   -  person Sobrique    schedule 15.06.2015
comment
Хорошо, с этой информацией @Amar есть другой вопрос. Я опубликовал ответ о том, что я считаю лучшим способом решения проблемы. Но в любом случае, возможно, стоит открыть новый вопрос.   -  person Sobrique    schedule 25.06.2015


Ответы (6)


Хэши не хранят ключи в надежном порядке. Такова природа хэшей, либо используйте функцию сортировки, либо используйте массив. См.: http://perldoc.perl.org/functions/keys.html

person Neil H Watson    schedule 15.06.2015

Мне кажется, что вы пытаетесь увидеть, существуют ли ключи; если так, попробуйте:

if( exists $data->{fileFooter} &&
    exists $data->{fileFooter}{measCollec} &&
    exists $data->{fileFooter}{measCollec}{endTime} &&
    exists $data->{fileHeader} &&
    exists $data->{fileHeader}{measCollec} &&
    exists $data->{fileHeader}{measCollec}{beginTime}
) {

или, если у вас установлено no autovivification;,

if( exists $data->{fileFooter}{measCollec}{endTime} &&
    exists $data->{fileHeader}{measCollec}{beginTime}
) {

или сделайте явно то, что no autovivification; делает для вас:

if ( exists ${ ${ $data->{fileFooter} || {} }{measCollec} || {} }{endTime} &&
    exists ${ ${ $data->{fileHeader} || {} }{measCollec} || {} }{beginTime}
) {
person ysth    schedule 15.06.2015
comment
Привет, @ikegami, я прикрепил к вопросу свой файл Script & xml. Не могли бы вы проверить, дайте мне знать, вышеизложенного достаточно, чтобы изменить сценарий?? - person Amar; 17.06.2015
comment
@ Амар, почему бы тебе не рассказать нам, если у тебя все еще есть проблема! - person ikegami; 17.06.2015
comment
@ikegami: Прости, чувак. Я не настолько хорош в Perl, чтобы писать и тестировать его. :/Кроме того, мне нужно несколько установок, таких как Linux, чтобы запустить этот скрипт, который будет бесплатным к завтрашнему дню. Я просто хочу подготовить свой код, чтобы я мог запустить и проверить его, как только получу настройку! - person Amar; 17.06.2015
comment
Есть несколько атрибутов xml, как показано ниже: ‹measValue measObjLdn=ManagedElement=1,Chassis=1,Slot=1,Eth1GbCard=1,Ethernet1GBPort=2› Как я могу написать свой фильтр для этих атрибутов?? - person Amar; 17.06.2015
comment
это звучит как совсем другой вопрос. хотя, если вы начнете новый вопрос, вам нужно будет быть намного более информативным, чем «Как я могу написать свой фильтр?» - person ysth; 17.06.2015

Да. Поскольку хэши по определению неупорядочены, функция ключей будет «вычисляться случайным образом».

Было бы лучше разобрать ваш xml на ссылки на массив.

Вы не можете рассчитывать на то, что хэш будет отображаться в одном и том же порядке раз за разом.

person Tim De Lange    schedule 15.06.2015

Ключи будут храниться в очевидно случайном (но не действительно случайном) порядке. Функции keys и values обещают каждый раз возвращать элементы в одном и том же порядке, но только при вызове одного и того же хеша. Другой хеш — даже если ключи одинаковые — может возвращать ключи в совершенно другом порядке. Изменение хеша также может изменить порядок ключей.

person Dondi Michael Stroma    schedule 15.06.2015
comment
Найдите файл xml в следующем месте: docs.zoho.com/writer/< /а> - person Amar; 17.06.2015

Хорошо, извините, что потребовалось некоторое время, чтобы вернуться к этому - легко пропустить обновления вопросов.

В любом случае, учитывая, что ваш скрипт выглядит как «собрать XML, проверить определенные ключи», я искренне думаю, что у нас может быть проблема с XY. Почему вы пытаетесь проверить свой XML, если вместо этого вы можете просто разложить его и выполнить поиск «по ключу»?

use strict;
use warnings;
use XML::Twig;

my %pos_lookup;

sub extract_measType {
    my ( $twig, $meastype ) = @_;
    my $pos = $meastype->att('pos');
    $pos_lookup{$pos} = $meastype->text;
}

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => { 'measType' => \&extract_measType }
);
$twig->parse( \*DATA );

foreach my $element ( $twig->root->get_xpath('measData/measInfo/measValue') )
{
    my $ldn = $element->att('measObjLdn');
    print "Data for: $ldn\n";
    foreach my $reading ( $element->children('r') ) {
        my $pos = $reading->att('pos');
        print "\t", $pos_lookup{$pos}, ":", $reading->text, "\n";
    }
}


__DATA__
<?xml version="1.0" encoding="UTF-8"?> 
 <measCollecFile> 
   <fileHeader fileFormatVersion="32.435 V10.0" dnPrefix="DC=ericsson.se,g3SubNetwork=Sweden"> 
     <fileSender localDn="ManagedElement=1,Chassis=1"/> 
     <measCollec beginTime="2015-06-08T05:06:58Z"/> 
   </fileHeader> 
   <measData> 
     <managedElement localDn="ManagedElement=1,Chassis=1"/> 
     <measInfo measInfoId="schema_profile_1"> 
       <granPeriod duration="PT60S" endTime="2015-06-08T05:06:58Z"/> 
       <repPeriod duration="PT60S"/> 
       <measType pos="1">inOctets</measType> 
       <measType pos="2">inPackets</measType> 
       <measType pos="3">mcastInOctets</measType> 
       <measType pos="4">mcastInPackets</measType> 
       <measType pos="5">mcastOutOctets</measType> 
       <measType pos="6">mcastOutPackets</measType> 
       <measType pos="7">meteringClassCounter</measType> 
       <measType pos="8">meteringPolicyName</measType> 
       <measType pos="9">outOctets</measType> 
       <measType pos="10">outPackets</measType> 
       <measType pos="11">policingClassCounter</measType> 
       <measValue 
measObjLdn="ManagedElement=1,Chassis=1,Slot=1,Eth1GbCard=1,Ethernet1GBPort=1"> 
         <r pos="1">337060</r> 
         <r pos="2">5616</r> 
         <r pos="3">0</r> 
         <r pos="4">0</r> 
         <r pos="5">0</r> 
         <r pos="6">0</r> 
         <r pos="7">(N/A)</r> 
         <r pos="8">(N/A)</r> 
         <r pos="9">1176</r> 
         <r pos="10">28</r> 
         <r pos="11">(N/A)</r> 
       </measValue> 
       <measValue 
measObjLdn="ManagedElement=1,Chassis=1,Slot=1,Eth1GbCard=1,Ethernet1GBPort=2"> 
         <r pos="1">1300</r> 
         <r pos="2">20</r> 
         <r pos="3">0</r> 
         <r pos="4">0</r> 
         <r pos="5">0</r> 
         <r pos="6">0</r> 
         <r pos="7">(N/A)</r> 
         <r pos="8">(N/A)</r> 
         <r pos="9">336936</r> 
         <r pos="10">5624</r> 
         <r pos="11">(N/A)</r> 
       </measValue> 
     </measInfo> 
   </measData> 
   <fileFooter> 
     <measCollec endTime="2015-06-08T05:06:58Z"/> 
   </fileFooter> 
 </measCollecFile> 

Теперь, если вы действительно хотите проверить наличие определенных вещей, я бы предложил поиск «get_xpath»:

my %to_check = (
    '/measCollecFile/measData/measInfo/measType[@pos="1"]' => 'inOctets',
    '/measCollecFile/measData/measInfo/granPeriod'         => '',
    '/measCollecFile/fileFooter/measCollec'                => '',
    '/some/bogus/value'                                    => "value",
);
foreach my $xpath ( keys %to_check ) {
    my $node = $twig->root->get_xpath( $xpath, 0 );
    my $value = "";
    if ($node) { $value = $node->text; }
    print $xpath, " => ", $value;
    if   ( $node and $value eq $to_check{$xpath} ) { print " OK\n"; }
    else                                           { print " ERROR\n"; }
}

Извините, я не воспроизвел вашу вещь полностью, но, надеюсь, это иллюстрирует идею? Я не думаю, что вам нужно делать столь же исчерпывающую проверку.

person Sobrique    schedule 25.06.2015

Один из способов подумать об этом — помнить, что вы получаете доступ к «значениям» в массиве по упорядоченным элементам в структуре данных (именно поэтому вы используете $array[2], @array[1,2,3] или $array_ref->[3]). С помощью хеша вы получаете доступ к «значениям» по их соответствующим ключам, которые могут быть в любом порядке, потому что вы обращаетесь к ним «неупорядоченным» способом.

См. Почему хеш-ключи имеют в другом порядке при печати? и другие сообщения, на которые есть ссылки на боковой панели «Похожее» для более подробного обсуждения.

person G. Cito    schedule 15.06.2015
comment
Привет всем, спасибо всем за ваши ценные комментарии. - person Amar; 17.06.2015