我之前曾问过这个问题 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;
}
我正在做的一些错误,如果有人可以帮助我,我无法抓住这些错误会很棒吗?
答案 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;