[PERL]-Compter en hexa

Bonjour,

je chercher un moyen de générer une série de nombre hexadécimaux en PERL en connaissant le début et la fin, mais je ne sais pas comment faire (je viens de me pendre avec la doc de pack/unpack ;-)).

J'ai un truc sous cette forme (extrait XML) :
        <Devices start_dev="005E" end_dev="005F"/>
        <Devices start_dev="0067" end_dev="0069"/>
        <Devices start_dev="006F" end_dev="006F"/>
        <Devices start_dev="0097" end_dev="009B"/>
        <Devices start_dev="00AA" end_dev="00AF"/>
        <Devices start_dev="00D2" end_dev="00D4"/>
        <Devices start_dev="00D6" end_dev="00DB"/>
        <Devices start_dev="00DF" end_dev="00DF"/>
        <Devices start_dev="00E4" end_dev="00E7"/>
        <Devices start_dev="00EB" end_dev="00FE"/>
        <Devices start_dev="0100" end_dev="0104"/>
        <Devices start_dev="0106" end_dev="0106"/>
        <Devices start_dev="011D" end_dev="011D"/>
Et je voudrais récupérer une liste comme ça :

005E, 005F, 0067, 0068, 0069, 006F, 0097, 0098, 0099, 009A, 009B, 00AA...

sachant que j'ai parfois des intervalles. Je devrais pourvoir récupérer mes bornes de début et de fin, mais faire générer les valeurs intermédiaires en hexa, je coince.

Si quelqu'un avait une idée (compréhensible par un humain qui n'est pas trappu en PERL :-))

Merci d'avance.

--
A+ Blux
 "Les cons, ça ose tout.
C'est même à ça qu'on les reconnait"

15 réponses

  1. Modérateur
    Salut,

    voici une possibilité
    $ cat blux
    <Devices start_dev="005E" end_dev="005F"/>
    <Devices start_dev="0067" end_dev="0069"/>
    <Devices start_dev="006F" end_dev="006F"/>
    <Devices start_dev="0097" end_dev="009B"/>
    <Devices start_dev="00AA" end_dev="00AF"/>
    <Devices start_dev="00D2" end_dev="00D4"/>
    <Devices start_dev="00D6" end_dev="00DB"/>
    <Devices start_dev="00DF" end_dev="00DF"/>
    <Devices start_dev="00E4" end_dev="00E7"/>
    <Devices start_dev="00EB" end_dev="00FE"/>
    <Devices start_dev="0100" end_dev="0104"/>
    <Devices start_dev="0106" end_dev="0106"/>
    <Devices start_dev="011D" end_dev="011D"/>
    $ perl -ne'/"([\da-f]{4})".*"([\da-f]{4})"/i;for$e(hex($1)..hex($2)){printf"%.4X,",$e}' blux && echo
    005E,005F,0067,0068,0069,006F,0097,0098,0099,009A,009B,00AA,00AB,00AC,00AD,00AE,00AF,00D2,00D3,00D4,00D6,00D7,00D8,00D9,00DA,00DB,00DF,00E4,00E5,00E6,00E7,00EB,00EC,00ED,00EE,00EF,00F0,00F1,00F2,00F3,00F4,00F5,00F6,00F7,00F8,00F9,00FA,00FB,00FC,00FD,00FE,0100,0101,0102,0103,0104,0106,011D,
    $
    j'ai utilisé echo pour passage à la ligne
    0
    1. Modérateur
      Merci, je vais essayer ça au boulot demain :-)

      <mode pénible>
      j'avais quand même dit : compréhensible par un humain...;-)
      Une question encore : si je lis ce fichier (qui ne contient pas que ça) ligne à ligne, je fais comment pour intégrer ces lignes dans mon programme, vu que je dois générer la séquence à chaque nouvelle entité XML que je trouve ?
      </mode pénible>
      0
      1. Modérateur
        si je lis ce fichier (qui ne contient pas que ça) ligne à ligne, je fais comment pour intégrer ces lignes dans mon programme, vu que je dois générer la séquence à chaque nouvelle entité XML que je trouve ?

        comme j'ai du mal à comprendre le langage humain ;-)) veux tu me donner un exemple concret
        0
        1. Modérateur
          Début de mon fichier :
          <SymCLI_ML>
            <symmetrix id="000184502760">
              <Devmask_Database_Record director="FA-3A" port="0">
                <Db_Record originator_port_wwn="10000000c92eb5fb"
                     awwn_node_name="10000000c92eb5fb" awwn_port_name="10000000c92eb5fb">
                  <Devices start_dev="0000" end_dev="001F"/>
                  <Devices start_dev="0070" end_dev="007F"/>
                  <Devices start_dev="00B0" end_dev="00BF"/>
                  <Devices start_dev="012E" end_dev="0130"/>
                  <Devices start_dev="0164" end_dev="0168"/>
                  <Devices start_dev="0205" end_dev="0205"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb544"
                     awwn_node_name="152101a001dbs" awwn_port_name="D1-08">
                  <Devices start_dev="0020" end_dev="0041"/>
                  <Devices start_dev="0080" end_dev="0085"/>
                  <Devices start_dev="0087" end_dev="0088"/>
                  <Devices start_dev="008A" end_dev="008F"/>
                  <Devices start_dev="00C2" end_dev="00C3"/>
                  <Devices start_dev="0131" end_dev="013C"/>
                  <Devices start_dev="013E" end_dev="0146"/>
                  <Devices start_dev="014F" end_dev="015D"/>
                  <Devices start_dev="0160" end_dev="0163"/>
                  <Devices start_dev="0169" end_dev="016B"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb6ee"
                     awwn_node_name="10000000c92eb6ee" awwn_port_name="10000000c92eb6ee">
                  <Devices/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb4d3"
                     awwn_node_name="10000000c92eb4d3" awwn_port_name="10000000c92eb4d3">
                  <Devices start_dev="0089" end_dev="0089"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb5ef"
                     awwn_node_name="10000000c92eb5ef" awwn_port_name="10000000c92eb5ef">
                  <Devices start_dev="0042" end_dev="004F"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb5aa"
                     awwn_node_name="10000000c92eb5aa" awwn_port_name="10000000c92eb5aa">
                  <Devices/>
                </Db_Record>
              </Devmask_Database_Record>
              <Devmask_Database_Record director="FA-3A" port="1">
                <Db_Record originator_port_wwn="10000000c92cfebd"
                     awwn_node_name="10000000c92cfebd" awwn_port_name="10000000c92cfebd">
                  <Devices/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c9341201"
                     awwn_node_name="10000000c9341201" awwn_port_name="10000000c9341201">
                  <Devices start_dev="0059" end_dev="0059"/>
                  <Devices start_dev="0211" end_dev="0211"/>
                </Db_Record>
              </Devmask_Database_Record>
          Je dois récupérer les infos concernant Devmask_Database_Record director, Db_Record originator_port_wwn ainsi que la liste des devices (en générant les numéros pour les intervalles). Je vais donc lire mon fichier ligne à ligne pour extraire mes infos mais je ne sais pas comment intégrer la commande ([\da-f]{4})".*"([\da-f]{4})"/i;for$e(hex($1)..hex($2)){printf"%.4X,",$e} pour lui dire qu'elle s'applique à la ligne courante...

          C'est plus clair ? :-)
          0
          1. Modérateur
            C'est plus clair ? :-)

            c'est ça que tu veux?
            #!/usr/bin/perl
            use strict;use warnings;
            my $devmask = '<Devmask_Database_Record director';
            my $dbrecord = '<Db_Record originator_port_wwn';
            my $awwn = 'awwn_node_name="';
            while (<DATA>){
                    s/\n// unless />$/;
                    print "\n$_" if /$devmask|$dbrecord|$awwn/;
                    if(/"([\da-f]{4})".*"([\da-f]{4})"/i){
                            for my $e(hex($1)..hex($2)){printf"%.4X,",$e}
                    }
            }
            print"\n";
            __END__
            <SymCLI_ML>
            <symmetrix id="000184502760">
            <Devmask_Database_Record director="FA-3A" port="0">
            <Db_Record originator_port_wwn="10000000c92eb5fb"
            awwn_node_name="10000000c92eb5fb" awwn_port_name="10000000c92eb5fb">
            <Devices start_dev="0000" end_dev="001F"/>
            <Devices start_dev="0070" end_dev="007F"/>
            <Devices start_dev="00B0" end_dev="00BF"/>
            <Devices start_dev="012E" end_dev="0130"/>
            <Devices start_dev="0164" end_dev="0168"/>
            <Devices start_dev="0205" end_dev="0205"/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c92eb544"
            awwn_node_name="152101a001dbs" awwn_port_name="D1-08">
            <Devices start_dev="0020" end_dev="0041"/>
            <Devices start_dev="0080" end_dev="0085"/>
            <Devices start_dev="0087" end_dev="0088"/>
            <Devices start_dev="008A" end_dev="008F"/>
            <Devices start_dev="00C2" end_dev="00C3"/>
            <Devices start_dev="0131" end_dev="013C"/>
            <Devices start_dev="013E" end_dev="0146"/>
            <Devices start_dev="014F" end_dev="015D"/>
            <Devices start_dev="0160" end_dev="0163"/>
            <Devices start_dev="0169" end_dev="016B"/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c92eb6ee"
            awwn_node_name="10000000c92eb6ee" awwn_port_name="10000000c92eb6ee">
            <Devices/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c92eb4d3"
            awwn_node_name="10000000c92eb4d3" awwn_port_name="10000000c92eb4d3">
            <Devices start_dev="0089" end_dev="0089"/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c92eb5ef"
            awwn_node_name="10000000c92eb5ef" awwn_port_name="10000000c92eb5ef">
            <Devices start_dev="0042" end_dev="004F"/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c92eb5aa"
            awwn_node_name="10000000c92eb5aa" awwn_port_name="10000000c92eb5aa">
            <Devices/>
            </Db_Record>
            </Devmask_Database_Record>
            <Devmask_Database_Record director="FA-3A" port="1">
            <Db_Record originator_port_wwn="10000000c92cfebd"
            awwn_node_name="10000000c92cfebd" awwn_port_name="10000000c92cfebd">
            <Devices/>
            </Db_Record>
            <Db_Record originator_port_wwn="10000000c9341201"
            awwn_node_name="10000000c9341201" awwn_port_name="10000000c9341201">
            <Devices start_dev="0059" end_dev="0059"/>
            <Devices start_dev="0211" end_dev="0211"/>
            </Db_Record>
            </Devmask_Database_Record>
            
            0
            1. Modérateur
              C'est un peu plus compliqué que ça :

              je voudrais avoir une ligne par device qui contienne les informations déjà rencontrées au niveau précédent, pour mon exemple, je souhaiterais obtenir ça en sortie :

              000184502760;FA-3A;0;10000000c92eb5fb;0000
              000184502760;FA-3A;0;10000000c92eb5fb;0001
              ...
              000184502760;FA-3A;0;10000000c92eb5fb;001F
              ...
              000184502760;FA-3A;0;10000000c92eb544;0020
              ...
              000184502760;FA-3A;1;10000000c9341201;0059
              ...

              Je récupère les infos suivantes : symmetrix id, Devmask_Database_Record director Devmask_Database_Record port, Db_Record originator_port_wwn, Devices start_dev et Devices end_dev, sachant que je n'ai pas toujours de Devices pour un Db_Record originator_port_wwn (cf mon exemple).

              J'ai commencé à regarder tes RE, mais j'ai décroché avec if(/"([\da-f]{4})".*"([\da-f]{4})"/i), j'avoue ne pas savoir comment le prendre...
              0
              1. Modérateur
                #!/usr/bin/perl
                use strict;use warnings;
                my($id,$dir,$wwn);
                while (<DATA>){
                  s/\n// unless />$/;
                  if(/id="([^"]+)"/)      {$id =$1}
                  if(/director="([^"]+)"/){$dir=$1}
                  if(/_wwn="([^"]+)"/)    {$wwn=$1}
                
                  if(/"([\da-f]{4})".*"([\da-f]{4})"/i){
                    for my $e(hex($1)..hex($2)){
                      printf"%s;%s;%s;%.4X\n",$id,$dir,$wwn,$e
                    }
                  }
                }
                print"\n";
                __END__
                <SymCLI_ML>
                <symmetrix id="000184502760">
                <Devmask_Database_Record director="FA-3A" port="0">
                <Db_Record originator_port_wwn="10000000c92eb5fb"
                awwn_node_name="10000000c92eb5fb" awwn_port_name="10000000c92eb5fb">
                <Devices start_dev="0000" end_dev="001F"/>
                <Devices start_dev="0070" end_dev="007F"/>
                <Devices start_dev="00B0" end_dev="00BF"/>
                <Devices start_dev="012E" end_dev="0130"/>
                <Devices start_dev="0164" end_dev="0168"/>
                <Devices start_dev="0205" end_dev="0205"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb544"
                awwn_node_name="152101a001dbs" awwn_port_name="D1-08">
                <Devices start_dev="0020" end_dev="0041"/>
                <Devices start_dev="0080" end_dev="0085"/>
                <Devices start_dev="0087" end_dev="0088"/>
                <Devices start_dev="008A" end_dev="008F"/>
                <Devices start_dev="00C2" end_dev="00C3"/>
                <Devices start_dev="0131" end_dev="013C"/>
                <Devices start_dev="013E" end_dev="0146"/>
                <Devices start_dev="014F" end_dev="015D"/>
                <Devices start_dev="0160" end_dev="0163"/>
                <Devices start_dev="0169" end_dev="016B"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb6ee"
                awwn_node_name="10000000c92eb6ee" awwn_port_name="10000000c92eb6ee">
                <Devices/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb4d3"
                awwn_node_name="10000000c92eb4d3" awwn_port_name="10000000c92eb4d3">
                <Devices start_dev="0089" end_dev="0089"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb5ef"
                awwn_node_name="10000000c92eb5ef" awwn_port_name="10000000c92eb5ef">
                <Devices start_dev="0042" end_dev="004F"/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c92eb5aa"
                awwn_node_name="10000000c92eb5aa" awwn_port_name="10000000c92eb5aa">
                <Devices/>
                </Db_Record>
                </Devmask_Database_Record>
                <Devmask_Database_Record director="FA-3A" port="1">
                <Db_Record originator_port_wwn="10000000c92cfebd"
                awwn_node_name="10000000c92cfebd" awwn_port_name="10000000c92cfebd">
                <Devices/>
                </Db_Record>
                <Db_Record originator_port_wwn="10000000c9341201"
                awwn_node_name="10000000c9341201" awwn_port_name="10000000c9341201">
                <Devices start_dev="0059" end_dev="0059"/>
                <Devices start_dev="0211" end_dev="0211"/>
                </Db_Record>
                </Devmask_Database_Record>
                                         
                0
                1. Modérateur
                  Waouh !!!

                  super-balaise! il me manque juste 2 choses : le port du meta Devmask_Database_Record et la compréhension de ce qui est écrit :-)

                  J'ai voulu faire moi-même la modif en regardant comment était faite la ligne qui extrait les dev, mais j'aurais pas dû (quand on sait pas, on touche pas...)
                  0
                  1. Modérateur
                    pour les explications un peu plus tard ;-))
                    #!/usr/bin/perl
                    use strict;use warnings;
                    my($id,$dir,$p,$wwn);
                    while (<DATA>){
                    #s/\n// unless />$/;
                      if(/id      ="([^"]+)"/x){$id =$1}
                      if(/director="([^"]+)"/x){$dir=$1}
                      if(/_wwn    ="([^"]+)"/x){$wwn=$1}
                      if(/port    ="([^"]+)"/x){$p  =$1}
                    
                      if(/"([\da-f]{4})".*"([\da-f]{4})"/i){
                        for my $e(hex($1)..hex($2)){
                          printf"%s;%s;%s;%s;%.4X\n",$id,$dir,$p,$wwn,$e
                        }
                      }
                    }
                    print"\n";
                    __END__
                    <SymCLI_ML>
                    <symmetrix id="000184502760">
                    <Devmask_Database_Record director="FA-3A" port="0">
                    <Db_Record originator_port_wwn="10000000c92eb5fb"
                    awwn_node_name="10000000c92eb5fb" awwn_port_name="10000000c92eb5fb">
                    <Devices start_dev="0000" end_dev="001F"/>
                    <Devices start_dev="0070" end_dev="007F"/>
                    <Devices start_dev="00B0" end_dev="00BF"/>
                    <Devices start_dev="012E" end_dev="0130"/>
                    <Devices start_dev="0164" end_dev="0168"/>
                    <Devices start_dev="0205" end_dev="0205"/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c92eb544"
                    awwn_node_name="152101a001dbs" awwn_port_name="D1-08">
                    <Devices start_dev="0020" end_dev="0041"/>
                    <Devices start_dev="0080" end_dev="0085"/>
                    <Devices start_dev="0087" end_dev="0088"/>
                    <Devices start_dev="008A" end_dev="008F"/>
                    <Devices start_dev="00C2" end_dev="00C3"/>
                    <Devices start_dev="0131" end_dev="013C"/>
                    <Devices start_dev="013E" end_dev="0146"/>
                    <Devices start_dev="014F" end_dev="015D"/>
                    <Devices start_dev="0160" end_dev="0163"/>
                    <Devices start_dev="0169" end_dev="016B"/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c92eb6ee"
                    awwn_node_name="10000000c92eb6ee" awwn_port_name="10000000c92eb6ee">
                    <Devices/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c92eb4d3"
                    awwn_node_name="10000000c92eb4d3" awwn_port_name="10000000c92eb4d3">
                    <Devices start_dev="0089" end_dev="0089"/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c92eb5ef"
                    awwn_node_name="10000000c92eb5ef" awwn_port_name="10000000c92eb5ef">
                    <Devices start_dev="0042" end_dev="004F"/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c92eb5aa"
                    awwn_node_name="10000000c92eb5aa" awwn_port_name="10000000c92eb5aa">
                    <Devices/>
                    </Db_Record>
                    </Devmask_Database_Record>
                    <Devmask_Database_Record director="FA-3A" port="1">
                    <Db_Record originator_port_wwn="10000000c92cfebd"
                    awwn_node_name="10000000c92cfebd" awwn_port_name="10000000c92cfebd">
                    <Devices/>
                    </Db_Record>
                    <Db_Record originator_port_wwn="10000000c9341201"
                    awwn_node_name="10000000c9341201" awwn_port_name="10000000c9341201">
                    <Devices start_dev="0059" end_dev="0059"/>
                    <Devices start_dev="0211" end_dev="0211"/>
                    </Db_Record>
                    </Devmask_Database_Record>
                    
                    0
                    1. Modérateur
                      J'avais fini par mettre une deuxième ligne, auparavant j'ai voulu essayer comme ce qui est fait pour extraire mes dev, mais ça l'a pas fait...
                      0
                      1. Modérateur
                        dit ce qui ne va pas, sur le bout de fichier que tu m'as donnée ça marche, mais c'est vrai que ce n'est pas évident
                        0
                        1. Modérateur
                          Je l'ai refait ce matin, à tête reposée, ça va mieux :
                            if (/"(FA-\d{1,2}[AB])".*"([\d])"/i)
                            {
                              $dir=$1;
                              $por=$2;
                            }
                          C'est sans doute pas optimisé, mais je ne suis qu'un humain ;-)
                          0
                          1. Modérateur
                            Affiche ton script modifié.

                            A vrai dire tu n'as pas besoin de faire comme ça, mais bon, je n'ai rien contre ;-)
                            Comme promis je vais t'expliquer ce que j'ai écrit, et tu verras que c'est vraiment humain :-)
                            0
                            1. Modérateur
                              while (<LIRE>)
                              {
                                s/\n// unless />$/;
                                if (/id      ="([^"]+)"/x)
                                {
                                  $id=$1;
                                }
                                if (/"(FA-\d{1,2}[AB])".*"([\d])"/i)
                                {
                                  $dir=$1;
                                  $por=$2;
                                }
                                if (/_wwn    ="([^"]+)"/x)
                                {
                                  $wwn=$1;
                                }
                                if (/"([\da-f]{4})".*"([\da-f]{4})"/i)
                                {
                                  for my $e(hex($1)..hex($2))
                                  {
                                    printf"%s;%s%s;%s;%.4X\n",$id,$dir,$por,$wwn,$e;
                                  }
                                }
                              }
                              

                              J'ai fini par presque tout comprendre excepté le ="([^"]+)

                              Mais je suis intéressé par une amélioration de mon if (/"(FA-\d{1,2}[AB])".*"([\d])"/i), même si elle n'est pas humaine (c'est juste pour voir ;-))
                              0
                              1. Modérateur
                                "([^"]+) "

                                trouve une " suivi d'un caractère non guillemet(une fois minimum) suivi d'une guillemet
                                ce qui permet de ne pas arriver sur la deuxième paire de guillemets

                                une amélioration de mon if (/"(FA-\d{1,2}[AB])".*"([\d])"/i),
                                peut être ça, mais je n'ai pas testé

                                if (/"(FA-[^"]+)".*"([\d])"/i)

                                0