从行

时间:2016-11-04 20:48:51

标签: perl

我之前曾问过这个问题 how to find the lengh of the input in an array and match pattern in perl

此处输入为十进制格式,稍后转换为十六进制

  

1.提取类型时我收到编译错误

" Global symbol "$type" requires explicit package name at test15.pl line 65."
" Global symbol "$type" requires explicit package name at test15.pl line 66."
  

2.当我检查了vals的输出并输入(通过评论最后几个     我的$ vals =到$ packed的代码行。
    我正在获得我在下面提到的值和类型

 0x01,uint8
 1440,Uint16
 0xbb3,Uint16
 ffffffbf,Sint8
 0xa3,uint32
  

3.我的正则表达式无法从行中间提取值

For e.g.
rrc_mac_interface   RLC_PDU { 1}    rrc_mac_interface   #default   type is uint8
gsm_lte_interface   scell + ncell + gsm cell { 3}   gsm_lte_interface   #default   type is uint8
reserved_for_data{3}    { 0, 0, 0 } Uint8,unsigned char 
  

我的输入行:

trans_id    1   uint8,unsigned char
Pdu_size    5120    Uint16, unsigned short  
sub_sfn         2995        Uint16, unsigned short
rrc_mac_interface   RLC_PDU { 1}    rrc_mac_interface   #default type is uint8
gsm_lte_interface   scell + ncell + gsm cell { 3}   gsm_lte_interface   
#default type is uint8
minvalue         -65    Sint8,signed char 
numtrx           163     uint32,unsigned short 
reserved_for_data{3}    { 0, 0, 0 } Uint8,unsigned char
my_st[1]      0         //do not match if the this line has []
  

代码:

use strict;
use warnings;
use feature qw( say );
my $inputfile  = 'input.txt';
my $outputfile = 'output.txt';
open my $my_ipfh, "<", $inputfile or die $!;
open my $my_opfh, ">", $outputfile or die $!;

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 (<$my_ipfh>)
 {      
 if (/([+-]?\d+)\s+ (uint8|sint8|Uint8|Sint8|uint16|sint16|Uint16|Sint16|uint32|sint32|Uint32|Uint32)/xg)
  {
    my ($vals, $type);
    $vals =$1;
    $vals =sprintf("0x%02x", $1);
    $type =$2;
    print "$vals,$type\n";
  }
    my @vals =
    map { unpack 'l', pack 'l', hex $_ }  # Convert to number and fix the sign   
    my $packer = $packers {$type} 
    or die("Unsupported type \"$type\"\n");  #error in this line
    $packed .= $packer->(@vals);

    say
    join ',',
     map { sprintf("0x%02X", $_) }
     unpack 'C*',
        $packed;
 }
  

我正在做的一些错误,如果有人可以帮助我,我无法抓住这些错误会很棒吗?

1 个答案:

答案 0 :(得分:2)

你问了一堆问题。我会报道一个。

  

提取类型时,我收到编译错误

my声明一个词法变量。它只存在于它所在的块中。

if( ...whatever... ) {
    my $something = 42;
}

print $something;

这与Javascript不同,其中var的范围是整个函数,无论你在哪里声明它。

$something阻止之外不存在

if。当use strict打开时,Perl不允许您使用未声明的变量,因此print语句将在编译时产生错误。

Read more about scoping in Perl here

这就是让你的缩进正确非常重要的原因。能够清楚,快速地查看范围是编程中最重要的事情之一。您的代码间距很小并且缩进。这是它的外观。

my $int_type_re = qr{
    ( [+-]? \d+ )
    \s+
    ( [us]int(?:8|16|32) )
}xi;

my $packed = '';
while (<$my_ipfh>) {
    if ( $_ =~ m{$int_type_re} ) {
        my ($vals, $type);
        $vals =$1;
        $vals =sprintf("0x%02x", $1);
        $type =$2;
        print "$vals,$type\n";
    }
    my @vals =
      map { unpack 'l', pack 'l', hex $_ };

    my $packer = $packers {$type} 
      or die("Unsupported type \"$type\"\n");  #error in this line

    $packed .= $packer->(@vals);
}

通过适当的4个字符缩进和良好的空行使用,while循环中的内容,if内的内容以及多行语句是什么更清晰。

我还将复杂的正则表达式从条件中移到了自己的变量中。这两个都给它一个名称,以帮助理解它正在做什么,它使条件更容易阅读。

我使用了/x正则表达式修饰符和换行符来清除正则表达式。然后,随着它分成小片,我看到我可以折叠重复的部分。

我还删除了/g正则表达式修饰符,因为它没有做任何事情。这是用于在单个字符串中循环多个匹配,如:

while( $x =~ /(\w+)/g ) {
    print "Word is $1\n";
}

或在列表上下文中:

my @words = $x =~ /(\w+)/g;