如何在数组中找到输入的长度并匹配perl

时间:2016-09-24 16:58:31

标签: perl

我是perl脚本的新手    我有这样的阵列    我的@array(0x0B,0x04,0x02767,0x0000,0xffffaf)    我的预期输出:    如果索引的长度大于4(我假设0x0B = 4)那么就做    拆分并加入这样的字符串    0x2767 - > 0x27,0x67    0xffffaf-> 0xff的,0xff的,0XAF

这里我试图找出输入字符串的长度和匹配    如果输入字符串的长度大于2并且匹配,则为pattern    那么它应该满足if条件

my $input = "0x0B";
# Name of the file the data is in
my $input_filename  = 'my_input_original.txt';

#要将输出转储到的文件的名称    my $ output_filename ='my_org_output.txt';

#打开文件    打开我的$ input_fh,“<”,$ input_filename或者死!$ ;;

#打开输出文件     打开我的$ output_fh,“>”,$ output_filename或者死!$ ;;至      我的$ output_filename ='my_org_output.txt'      我更新的代码我想做什么

here is what i want to do
my input 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
my_output:

0x0B,0x0C,0x4A,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,
0x00,0x00,0x0A,0x00,0x00,0x00

1.if the line contain Uint16 then pad with 0x00 with the value

2.if the line contain the value with 0x2767 split and join 
 with(e.g.0x2767->0x27,0x67) or 
 0xffffaf (0xffffaf->0xff,0xff,0xaf)
my code :
#here is extracting only hex value
while ($_ =~ m/(0x(\d+)(?:[0-9]|[A-f])+)/gi)
{
 push @hex_array, $1; # here i get only hex value of for my input data
 #here if the array contain index value more than two then i need to
 #split the data and join also if the line contain Uint16 then i need to 
 #padd with 0x00 before the value (for e.g. 0x04-->0x00,0x04)
  foreach my $element (@hex_array) 
    {
   my @parts;
  if (4 < length $element) 
   {
    pos $element = 2;  # skip 0x
    @hex_array = map "0x$_", $element =~ /../g;
 } else 
 {
    @hex_array = $element;
 }
}
}
# Write the data to the file
print {$output_fh} join("U, ", @hex_array);
please help me

2 个答案:

答案 0 :(得分:2)

&#34;索引&#34;数组元素通常是数字,而不是元素本身。 =~是绑定运算符,我怀疑你想从一个数字比较的长度创建一个正则表达式。 但我想你想要这样的东西:

#!/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;
}

即。如果元素超过4个字符,则获取除第一个字符之外的字符对,将0x添加到它们之前,然后输出。

如果你不介意从短输入中删除0x并将其放回原点,那么代码可能会被简化:

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

答案 1 :(得分:0)

听起来你有一堆32位的值为十六进制,并且你想将它们打包成指定的big-endian类型,并且你想要一个打包结构的十六进制表示。

(请注意,这假设您对gtotal的输出有误。如果我理解正确,0xffffffaf表示-810xAF为{{1} }}。)

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