- 论坛徽章:
- 1
|
好活动,支持一下。
到现在工作近6年了,前面三年在国企,由于工作环境和视野所限,对脚本基本忽视,一直秉承着C/C++才是语言的王道,我记得有一次,用fopen等C库函数来解析ELF文件,累死了。后来到了外企上班,才发现脚本应用之广,在这里接触到了PowerShell,VBA,VBS,Perl。
但是真正下力学的还是Perl,原因只有三个:
1:看到对面的同事学习,心里争强好胜,也要学习一下。
2:Perl语言的发明者是个语言学家,很牛的一个人,想系统学习一下Perl,领悟其编程思想。
3:用Perl作一些文本解析工作,比如我做的是汽车电子,经常会接触到CAN Message Log文件,用Perl提取其中的个别消息,那是极其便利的。
使用CANoe记录CAN消息格式如下:
0.175826 1 151 Tx d 8 00 03 00 80 00 00 00 00 Length = 960000 BitCount = 123 ID = 337
0.184991 1 221 Rx d 8 29 55 2E F1 00 00 00 00 Length = 928000 BitCount = 119 ID = 545
0.186886 1 161 Tx d 8 02 FF FF FF 00 00 00 00 Length = 952000 BitCount = 122 ID = 353
其中55,2E,F1这三个位置的数据是我关心的数据,所以要将其突出显示,在两边加上中括号,并单独提出出来放到文件中,代码如下:
use strict;
my $SourceFileAddAndName1;
my $NewFileAddrAndName1;
my $SourceFileAddAndName;
my $NewFileAddrAndName;
my $CANHandle;
my $CANNewFile;
*WITH_COMMENT=\1; #特别注意常量的使用方式
*NO_COMMENT=\0;
#注意:这里使用文件句柄时带了$,只有这样才可实现文件句柄作为函数参数传递
open($CANHandle,"D:\\ReversingProblem\\4.ASC" || die "$!";
open($CANNewFile,">D:\\ReversingProblem\\4Filtered.ASC" || die "$!";
#open($CANNewFile,">D:\\NoObstacleFilted.txt" || die "$!";
#函数的四个参数意义
#FirstPara:new file handle
#SecondParadl file handle
#ThirdPara:Message ID
#FourthParam:the left distance from Rx
#FifthParam:the right distance from Rx
GetUsefulMsg($CANNewFile, $CANHandle, 161,10,19,*NO_COMMENT);
#关闭文件
close CANHandle;
close CANNewFile;
open($CANNewFile,"D:\\NoObstacleFilted.txt" || die "$!";
#处理文件的每一行
while(<$CANNewFile>
{
my $Num2Value = GetDecValueByByteIndexAndNum(1);
#得到一个字节的数据信息
my $DecValue = GetDecValueFromMsg($_,$Num2Value,1);
#print $DecValue, "," ,$Num2Value, "...\n";
}
###############################################################
################
###############################################################
sub ProcessFileAddress
{
my ($FileAddrAndName)=@_;
#"\-->\\",使用正则表达式将一条反w斜线换成二条
$FileAddrAndName=~s/\\/\\\\/;
return $FileAddrAndName;
}
sub GetUsefulMsg
{
my ($NewFileHandle,$SourceFileHandle,$MsgID,$StartDis,$EndDis,$CommentInfo)=@_;
while(<$SourceFileHandle>
{
#两个空格中间夹着消息ID,其格式如:
#0.175826 1 151 Tx d 8 00 03 00 80 00 00 00 00 Length = 960000 BitCount = 123 ID = 337
#0.184991 1 221 Tx d 8 29 55 2E F1 00 00 00 00 Length = 928000 BitCount = 119 ID = 545
#0.186886 1 161 Tx d 8 02 FF FF FF 00 00 00 00 Length = 952000 BitCount = 122 ID = 353
#其中,55,2E,F1这三个位置是要突出显示的,添加中括号突出显示效果如下:
#0.186886 1 161 Tx d 8 02 [FF FF FF] 00 00 00 00 Length = 952000 BitCount = 122 ID = 353
if($_=~/\s$MsgID\s/) #正则表达式中也可以实现变量内插,MsgID就是前面的151,221,161,这些是CAN消息ID。
{
if($CommentInfo == *WITH_COMMENT)#如果要添加注释
{
#the two line is used to comment the data
#使用()实现a匹配捕捉,
#添加中括号,以便于查看
#这里的\1表示小括号中的a匹配的内容,好像用$1也是可以的
s/Rx(.{$StartDis})/Rx\1\[/;#添加d左中括号
s/Rx(.{$EndDis})/Rx\1\]/;#添加右中括号
}
print $NewFileHandle $_;#将结果r打印到文件,注意文件句柄后面没有逗号
}
}
}
#first Param:the index of the request message,文件每一行的内容
sub GetDecValueByByteIndexAndNum
{
#得到Rx在一个串中开始的索引值,因为时间长度不同,比如有的是0.001s,有的是100.111s,相应的每行文字字符串的长度也不同,
#Rx位于字符串的位置索引也是不同的
my ($ByteIndex)=@_;
#查找Rx的位置。
my $RevDis=index($_,"Rx "
if($RevDis != -1)
{
return $RevDis+9+3*$ByteIndex;
}
return undef;
}
#first param:message line,type $,文件每一行的内容。
#second Param:the left distance from Rx,这里是指从Rx中的“x”字符向右数,第几个位置。比如对于
Rx d 8 29 55 2E F1 00 00 00 00,如果想要提取55这个数据,那么对应的位置就是9。
#third Param:the number,提取字节的数量,
sub GetDecValueFromMsg
{
#得到输入参数
my ($LineContent,$LeftDisFromRx, $ByteNum)=@_;
#将串分割成数组,当成数字来对待
my @ContentArray=split(//,$LineContent);
#从CAN的8字节消息中提取数据信息,这里提取的信息可能是1,2,3,4字节,
my $HexValue=0;
if($ByteNum==1)
{
$HexValue=@ContentArray[$LeftDisFromRx].@ContentArray[$LeftDisFromRx+1];
}
elsif($ByteNum==2)
{
$HexValue=@ContentArray[$LeftDisFromRx].@ContentArray[$LeftDisFromRx+1]
.@ContentArray[$LeftDisFromRx+3].@ContentArray[$LeftDisFromRx+4];
}
elsif($ByteNum==3)
{
$HexValue=@ContentArray[$LeftDisFromRx].@ContentArray[$LeftDisFromRx+1]
.@ContentArray[$LeftDisFromRx+3].@ContentArray[$LeftDisFromRx+4]
.@ContentArray[$LeftDisFromRx+6].@ContentArray[$LeftDisFromRx+7];
}
elsif($ByteNum==4)
{
$HexValue=@ContentArray[$LeftDisFromRx].@ContentArray[$LeftDisFromRx+1]
.@ContentArray[$LeftDisFromRx+3].@ContentArray[$LeftDisFromRx+4]
.@ContentArray[$LeftDisFromRx+6].@ContentArray[$LeftDisFromRx+7]
.@ContentArray[$LeftDisFromRx+9].@ContentArray[$LeftDisFromRx+10];
}
else
{
$HexValue=undef;
}
#进制转化
return hex($HexValue);
}
|
|