巧用AWK处理二进制数据文件[网络技术]
本文“巧用AWK处理二进制数据文件[网络技术]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
根源:豆豆网
AWK是Unix下的一款功效强盛的文本格局化和抽取工具.操纵这个工具,可以对复杂的文本文件举行整理,提取此中的全部大概部份数据,按照需求的格局予以显示.需求阐明的是,AWK的强盛功效只针对纯文本文件.关于带有很多不可显示字符的二进制数据文件,单凭AWK就无能为力了.这时我们需求其他工具的帮忙.
在Unix下,还有一个工具叫做OD,其全称是“display files in octal format”,也就是说它能将各种文件以8进制的方法显示出来.假如设置差别的选项,它还能将文件以16进制方法显示.
此外为了便利处理,我们还需求用到别的一个工具,sed.这也是一个Unix下的传统文本处理工具.在这里我们主要用到它的文本替换功效.
通过组合以上三种工具,我们便可以完成我们用AWK处理二进制数据文件的任务了.
笔者手中有一个数据文件,FXT,其数据构造如表 1所示.
Table 1
起始位 长度 阐明
0 8 账号
8 7 金额
15 3 操作员号
假如用普通的文本编辑器翻开这个数据文件,看到是一串数字和一堆难以理解的字符.根本就无法辨别金额是多少.为了便利读者理解这个文件,我们用od来查看这个文件 (见List1).
List 1
# od -An -v -tx1 FXT
32 35 38 35 36 30 30 39 00 00 05 00 00 00 0c 31
30 31 0a 32 35 38 30 30 32 33 34 90 20 20 80 20
20 0d 31 30 32 0a …
略微注释一下Od的号令参数意义.-An表示不在每行左边显示偏移量;-v 表示每行都要显示;-tx1表示输出时以16进制方法输出,一次一个字节.
按照数据构造定义,我们可以看出前面8个字节(32 35 38 35 36 30 30 39)代表账号,并且账号部份是由可显示的ASCII码构成的,翻译后的后果就是25856009;接下来7个字节(00 00 05 00 00 00 0c)代表金额.最后的c代表credit,就是贷方的意思.它所代表的实际金额是500,000.00.紧接着的3个字节代表操作员号,也是由可显示的 ASCII码构成的.0a是换行符的ASCII代码,表示一条记录完毕.
可以看出,恰是由于金额部份是由不可显示的ASCII码构成,招致了无法用通例办法来提取数据文件中的数据.
那么应当若何操纵以上的工具来处理这类数据文件,并且按照可以理解的方法来生成新的纯文本的数据文件呢?
OD 已经将整个数据文件清楚地显示出来了.它输出的格局不符合我们的要求.比方说,本来在一行的记录,先在给分成了几行;本来连在一同的字符,目前中间呈现了空格.这样AWK就不好处理了.所以,为了使AWK可以便利的处理,我们在正式提取数据之前,必须生成AWK可以处理的中间文件.
从List1可以看出,OD在显示文件时,每一行前都有一个制表符,并且本来记录之间的换行符也变成了对应的ASCII码0a.那么我们的任务就要去掉制表符,并且要恢复精确的记录间的换行符.这一步可以通过以下号令完成.
# od -v -An -tx1 fxt |sed 's/ //'|sed 's/0a/,/'|awk -f org.awk >fxt.a
OD显示出的后果通过管道被送给sed.Sed将每行开首的制表符先去掉,然后将0a字符替换为逗号.然后交给org.awk做格局化处理.
# cat org.awk
BEGIN{
ORS=""
}
{
for(i=1;i<17;i++)
{
if($i==",")
printf("\n");
else
printf("%s", $i);}
}
通过定义ORS=””,我们可以保证输出的每个字段之间没有脱离符.(ORS=Output Record Separator).然后,查抄每一行中能否存在逗号,假若有则输出一个换行符.这样我们就把od显示的后果转化成以下内容.
# cat fxt.a
32353835363030390000050000000c313031
32353830303233349020208020200d313032
怎么样,这样的格局就顺眼多了吧.
生成了中间文件,下一步就应当做正式的数据提取工作了.在实际工作中,极大概原始数据文件中的数据构造和我们需求转换的目标数据构造不完好一致.这时除了提取数据,还要在输分外式上举行一番加工.比方以上的数据文件,假如要按照以下数据构造(Table 2)输出的话,那么便可以参照程序ck1.awk.
Table 2
起始位 长度 阐明
0 12 账号
12 1 ,
13 1 假贷标志,0表示贷,1表示借
14 1 ,
15 14 金额
29 1 ,
30 3 操作员号
# cat ck1.awk
BEGIN{
FS="\n"; }
function trans(s)
{
if((a=substr(s,1,2)-30)<0)
a=0;
for(i=3;i<length(s);i+=2)
{
if((b=substr(s,i,2)-30)<0)
b=0;
a=(a b);
}
return a;
}
{
actno=trans(substr($1,1,16));#帐号
amt=substr($1,17,13);#金额
cdflag=substr($1,30,1); #假贷标志
if(cdflag=="d")
cdflag=1;
if(cdflag=="c")
cdflag=0;
oper=trans(substr($1,31,6));#操作员号
printf("%-12s,%s,%014d,%s\n", actno,cdflag,amt,oper);
}
一个AWK程序分成三个部份,开始,中间处理和完毕部份.开始部份用BEGIN{}表示,完毕部份用END{}表示,而中间部份用{}围起来便可.BEGIN部份是在正式处理开始之前,做的一些预备工作.而END就是在全部记录都处理完毕之后,做的一些扫尾的工作.
大家可以看到,AWK的语法和C语言很相近,还可以定义函数.而事实上AWK的确在很多地方上都近似于C,所以对C语言有底子的读者应当很快就可以掌握AWK的用法.
首先,在开始部份,我们将字段脱离符FS设为\n,就表示将一行作为一个字段来处理.
其次,我们定义了一个函数trans.其功效主如果将用ASCII码方法表示的数字字符给复原成正常的数字情势.数字0-9的ASCII码对应为 30-39.所以要将一个ASCII码转化成对应的数字,只要将该ASCII码减去30便可.比方1的ASCII码为31,那么31 - 30 =1 就很快得出了31所对应的数字.Trans函数恰是利用了这一原理,将ASCII码转换成对应的数字,然后将这些数字衔接起来,形成账号大概操作员号,返回给调用者.
以上是“巧用AWK处理二进制数据文件[网络技术]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |