使用shell和awk批量处理二进制数据

   接到个任务,需要批量处理10万个HDCP key的二进制文件,需要把前320个字节的十六进制的和相加,并且用65536减去和,然后将所得结果写到二进制文件特定的位置(具体是0x140h和0x141h),高位在前,低位在后

如下图1红色部分所示。





                                                                                                         图1

  

  得到需求后,我在思考用什么方式来实现批量处理,感觉linux里面的shell正非常适合处理这种批量数据。由于需要累加这些二进制文件里面的数据

不太好直接处理,我就先把他们从二进制转化为ASCII的文本形式,然后把数据转化为十进制方便一些(要不然直接类似于FF+10这种会出问题,用awk

把这些数据切割好,然后累加

#change to ASCII Txt
   od -An -v -tx1 $filename  > $file_txt
   awk  'BEGIN{FS=" ";total = "0x"} {if(NR<=20){for(i =1;i<17;i++){c =   (total""$i);print c}} }' $file_txt > $file_txt"_1"


   awk --non-decimal-data   -F, '{printf "%d\n",$1}' $file_txt"_1" >> $file_txt"_2"

接着计算校验和

#calculate the checksum
   awk  'BEGIN{FS=" ";total = 0} {if(NR<=320){for(i=1;i<2;i++){total+=$i;}} }END{print FILENAME;printf "0x%x\n",(65536-total)}' $file_txt"_2"


   checksum=`awk  'BEGIN{FS=" ";total = 0} {if(NR<=320){for(i=1;i<2;i++){total+=$i;}} }END{printf "%x\n",(65536-total)}' $file_txt"_2"`
   


然后把得到的校验和分为高位低位

  #在$string中从位置$position开始提取$length长度的子串.
   checksum_l=`echo ${checksum:0:2}`;
   echo $checksum_l;
   checksum_h=`echo ${checksum:2:2}`;
   echo $checksum_h;


最后就是写回二进制文件了

#write back to the original files
   printf "\x""$checksum_l" | dd of=$filename  bs=1 count=1 conv=notrunc bs=1 count=1 seek=321

   printf "\x""$checksum_h" | dd of=$filename  bs=1 count=1 conv=notrunc bs=1  count=1 seek=320


基本的功能是实现了,剩下的一些小的细节,批量处理,由于hdcp key的文件名是从HDCPkey000001.bin到HDCPkey999999.bin

那么我们直接用for循环搞定吧,如下

count=$1;
i=1;
filename_start="HDCPkey";
filename_end=".bin";
for i in `seq $i $count`
do
   if [ $i -lt 0 ];then
       echo "input $i error!\n";
       exit 1; 
   elif [   $i -ge 1 ]  && [  $i -lt 9  ];then
       filename_start="HDCPkey00000";   
   elif [ $i -ge 10  ]  && [ $i -lt 99 ];then
       filename_start="HDCPkey0000";
   elif [ $i -ge 100 ]  && [ $i -lt 999 ];then
       filename_start="HDCPkey000";
   elif [ $i -ge 1000 ] && [ $i -lt 9999 ];then
       filename_start="HDCPkey00";
   elif [ $i -ge 10000 ] && [ $i -lt 99999 ];then
       filename_start="HDCPkey0";
   elif [ $i -ge 100000 ] && [ $i -lt 999999 ];then
       filename_start="HDCPkey";


   
   fi
   filename=${filename_start}${i}"${filename_end}";
   file_txt=${filename_start}${i};

 ..................  //这里省略部分语句

done


这样做完之后,我测试了下竟然花了十几分钟才全部处理完所有的数据,

后面我自己又加了个多线程的方式,只要几分钟就能处理好,已经上传了,请自行查阅。


http://download.csdn.net/detail/liujian88/9344141






版权声明:本文为liujian88原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。