how to find the lengh of the input in an array and match pattern in perl

前端 未结 2 1472
南旧
南旧 2020-12-22 13:46

i am new to to the perl scripting i have an array like this my @array (0x0B,0x04,0x02767,0x0000,0xffffaf) my expected output: if the length of the index is more

相关标签:
2条回答
  • 2020-12-22 14:28

    The "index" of an array element is usualy the number, not the element itself. =~ is the binding operator, I doubt you want to create a regex from a length of a numeric comparison. But I guess you want something like this:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use feature qw{ say };
    
    my @array = qw( 0x0B 0x04 0x02767 0x0000 0xffffaf );
    for my $element (@array) {
        my @parts;
        if (4 < length $element) {
            pos $element = 2;  # skip 0x
            @parts = map "0x$_", $element =~ /../g;
        } else {
            @parts = $element;
        }
        say join ', ', @parts;
    }
    

    I.e. if the element is longer than 4 characters, get pairs of its characters except the first one, prepend 0x to them, and output.

    The code might be simplified if you don't mind burning some CPU cycles on removing 0x from the short inputs and putting it back:

    my @array = qw( 0x0B 0x04 0x02767 0x0000 0xffffaf );
    for my $element (@array) {
        pos $element = 2;  # skip 0x
        my @parts = map "0x$_", $element =~ /../g;
        say join ', ', @parts;
    }
    
    0 讨论(0)
  • 2020-12-22 14:47

    Sounds like you have a bunch of 32-bit values as hex, and that you want to pack them into the specified big-endian type, and that you want a hex representation of the packed structure.

    (Note that this assumes you are wrong about the output for gtotal. If I understand correctly, 0xffffffaf means -81, which is 0xAF as a Sint8.)

    use strict;
    use warnings;
    use feature qw( say );
    
    my %packers = (
       Uint8  => sub { pack 'C*',  @_ },
       Sint8  => sub { pack 'c*',  @_ },
       Uint16 => sub { pack 'S>*', @_ },
       Sint16 => sub { pack 's>*', @_ },
       Uint32 => sub { pack 'L>*', @_ },
       Sint32 => sub { pack 'l>*', @_ },
    );
    
    my $packed = '';
    
    while (<DATA>) {
       my ($vals, $type);
       if (/^\S+ \s+ \{ \s* ( 0x[0-9a-fA-F]+ (?: \s* , \s* 0x[0-9a-fA-F]+ )* ) \s* \} \s+ ([^\s,]+) /x) {
          $vals = $1;
          $type = $2;
       }
       elsif (/^\S+ \s+ ( 0x[0-9a-fA-F]+ )\s+ ([^\s,]+) /x) {
          $vals = $1;
          $type = $2;
       }
       else {
          die("Unrecognized syntax at line $.\n");
       }
    
       my @vals =
           map { unpack 'l', pack 'l', hex $_ }  # Convert to number and fix the sign
              split /\s*,\s*/,
                 $vals;
    
       my $packer = $packers{$type}
          or die("Unsupported type \"$type\"\n");
    
       $packed .= $packer->(@vals);
    }
    
    # say sprintf '%v02X', $packed;
    
    say
       join ',',
          map { sprintf("0x%02X", $_) }
             unpack 'C*',
                $packed;
    
    __DATA__
    total_sum   0x0B    Uint8,unsigned char
    num     0x0C    Uint8,unsigned char
    max     0x4A    Uint8,unsigned char
    padd    0x00     Uint8,unsigned char
    ideal   0x01    Uint16, unsigned short
    newtext{2}  { 0x00, 0x00 }  Uint8,unsigned char
    my_new  0x02     Uint16, unsigned short
    newtest2{2} { 0x00, 0x00 }  Uint8,unsigned char
    xyz         0x0A     Uint8,unsigned char
    newtest4{3} { 0x00, 0x00, 0x00 }    Uint8,unsigned char
    gtotal 0xffffffaf   Sint8,signed char
    info    0x2767  Uint16, unsigned short
    

    Output:

    0x0B,0x0C,0x4A,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x0A,0x00,0x00,0x00,0xAF,0x27,0x67
    
    0 讨论(0)
提交回复
热议问题