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
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;
}
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