如何巧用AWK处理二进制数据文件?

作者&投稿:类疯 (若有异议请与网页底部的电邮联系)
linux用awk计算二进制文件中的数值和~

awk '{if (NR < 20){for (i=2; i<18; i++){sum += $i;}}else{exit;}} END{printf "Total:%x
", sum; }' $file


$file是你的文件名

不用awk的方法示例:
echo "ibase=10;obase=2; 123" | bc
则会输出1111011
其中ibase表示输入的进制,obase表示输出的进制,123就是你要转化的十进制数,

使用awk的方法,因为awk中有十进制、八进制、十六进制的格式化输出,恰好没有二进制的,所以需要自己转化一下,其中一种方法如下:
echo 235 | awk 'BEGIN{m[0]="000";m[1]="001";m[2]="010";m[3]="011";m[4]="100";m[5]="101";m[6]="110";m[7]="111"}{ s = sprintf("%o",$0); for(i=1;i<=length(s);i++) printf ("%s", m[substr(s,i,1)]); printf("
");}'

前面的echo 235 就是把输入送给awk程序,235就是想要转化的十进制数,上面结果的输出为011101011
注意前置的0没有去掉,若想要去掉,可以考虑后面在对01串稍微处理一下。

AWK是Unix下的一款功能强大的文本格式化和抽取工具。利用这个工具,可以对复杂的文本文件进行整理,提取其中的全部或者部分数据,按照需要的格式予以显示。需要说明的是,AWK的强大功能只针对纯文本文件。对于带有很多不可显示字符的二进制数据文件,单凭AWK就无能为力了。这时我们需要其他工具的帮助。   在Unix下,还有一个工具叫做OD,其全称是“display files in octal format”,也就是说它能将各种文件以8进制的方式显示出来。如果设置不同的选项,它还能将文件以16进制方式显示。  此外为了方便处理,我们还需要用到另外一个工具,sed。这也是一个Unix下的传统文本处理工具。在这里我们主要用到它的文本替换功能。  通过组合以上三种工具,我们就可以完成我们用AWK处理二进制数据文件的任务了。  笔者手中有一个数据文件,FXT,其数据结构如表 1所示。  Table 1起始位长度说明08账号87金额153操作员号  如果用普通的文本编辑器打开这个数据文件,看到是一串数字和一堆难以理解的字符。根本就无法分辨金额是多少。为了方便读者理解这个文件,我们用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起始位长度说明012账号121,131借贷标志,0表示贷,1表示借141,1514金额291,303操作员号# 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码转换成对应的数字,然后将这些数字连接起来,形成账号或者操作员号,返回给调用者。  在正式处理部分,我们大量的运用了substr函数。这是个内置函数,是用于提取字符串中的部分字符。要记住,通过OD的转换之后,我们这里用2位数字代表一个字节。所以账号虽然是8个字节,而我们提取时,要取16个字节。  此外,由于账号和操作员号现在是以ASCII方式表示,所以需要通过trans函数翻译一下。而金额部分由于是直接由16进制ASCII码值来表示了,反倒不用再翻译了。  输出时用到了printf函数。这个函数的用法和标准的C语言printf函数用法完全一样。根据输出数据结构的要求,printf对帐号和金额进行了修饰,使得帐号左对齐且长度为12个字节,用空格对后面不足部分进行填充;而金额部分用前导零填充。  执行以上程序,就得到了我们想要的结果。# awk -f ck1.awk fxt.a 
25856009  ,0,00000050000000,101 
25800234  ,1,00000208020200,102 


如何巧用AWK处理二进制数据文件?
} 一个AWK程序分成三个部分,开始,中间处理和结束部分。开始部分用BEGIN{}表示,结束部分用END{}表示,而中间部分用{}围起来即可。BEGIN部分是在正式处理开始之前,做的一些准备工作。而END就是在全部记录都处理完毕之后,做的一些扫尾的工作。大家可以看到,AWK的语法和C语言很相近,还可以定义函数。...

巧用awk:如何把多行日志变成一行
如果是所有的行都变成1行,可以用:awk '{printf "%s", $0}' 日志文件名 如果是每N行变一行可以(以N=3为例)awk '{printf "%s", $0}NR%3==0{printf "\\n"}' 日志文件名

linux运维必须知道的几个常用命令
安装和登录命令:login 、shutdown 、halt 、reboot 、mount 、umount 、chsh 文件处理命令:file 、mkdir 、grep 、dd 、find 、mv 、ls 、diff 、cat 、ln 网络操作命令:ifconfig 、ip 、ping 、netstat 、telnet 、ftp 、route 、rlogin rcp 、finger 、mail 、nslookup 系统安全相关命令:pas...

C语言怎么用正则表达式
如果调用函数regcomp()或regexec()得到的是一个非0的返回值,则表明在对正则表达式的处理过程中出现了某种错误,此时可以通过调用函数regerror()得到详细的错误信息。size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);参数errcode是来自函数regcomp()或regexec()...

如何学好java语言啊?
一:Javase基础 二:网页三剑客html+css+js 三:JavaWeb和数据库:四:JavaEE框架:企业级开发,Struts2、Spring框架、Hibernate框架、Maven核心技术、MyBaits框架、高手进阶;如果找不到学习资源,可以点击这里下载。当你学完了Java,应该如何去找工作?一.最重要的还是自身技能,这是硬件标准,标配,自己...

孙权劝学
蒙曰:“士别三日,即更刮目相待,大兄何见事之晚乎!”肃遂拜蒙母,结友而别。二、译文起初,吴王孙权对大将吕蒙说道:“你现在身当要职掌握重权,不可以不去学习呀!”吕蒙以军营中事务繁多为理由加以推托。孙权说:“我难道是想要你成为精通儒家书籍、传授经学的学官吗?你只应当粗略地阅读,了解了解历史。你说你...

js正则怎么判断一个字符串里必须包含大写字母,小写字母,数字,特殊字符...
上述正则表达式规定字符m可以在匹配对象中连续出现2-6次,因此,上述正则表达式可以同jimmy或jimmmmmy等字符串相匹配。在对如何使用正则表达式有了初步了解之后,我们来看一下其它几个重要的元字符的使用方式。\\s:用于匹配单个空格符,包括tab键和换行符;\\S:用于匹配除单个空格符之外的所有字符;\\d:...

米酒的功效与作用
一: 对畏寒、血淤、缺奶、风湿性关节炎、腰酸背痛及手足麻木等症,以热饮为好;米酒二: 对神经衰弱、精神恍惚、抑郁健忘等症,加鸡蛋同煮饮汤效果较佳;三: 米酒能够帮助血液循环,促进新陈代谢,具有补血养颜、舒筋活络、强身健体和延年益寿的功效.四: 产妇血淤、腰背酸痛、手足麻木和震颤、风湿性...

庐山区13793833513: 如何用AWK处理二进制数据文件?
上曼凡林: AWK是Unix下的一款功能强大的文本格式化和抽取工具.利用这个工具,可以对复杂的文本文件进行整理,提取其中的全部或者部分数据,按照需要的格式予以显示.需...

庐山区13793833513: 如何巧用AWK处理二进制数据文件? -
上曼凡林: 是指压缩数据文件? .Z .gz 等后缀的? zcat 文件名 可以查看文件内容 加个管道 再接awk语句 eg: zcat test.txt.gz | awk '{print $1}'

庐山区13793833513: 我输入一个数字,想在awk里执行命令,把变量变为2进制,该如何做? -
上曼凡林: 你好!你是想输出这个二进制数呢,还是按位存储起来?写详细一点啦如有疑问,请追问.

庐山区13793833513: 二进制的处理数据 -
上曼凡林: 我们在使用数据库时,有时会用到图像或其它一些二进制数据,这个时候你们就必须使用getchunk这个方法来从表中获得二进制大对象,我们也可以使用AppendChunk来把数据插入到表中.我们平时来取数据是这样用的!Getdata=rs(fieldname) ...

庐山区13793833513: 请教如何使用awk从文件中读取十六进制列的问题 -
上曼凡林: 使用 --non-decimal-data选项, 将十六进制数据转化为10进制并打印

庐山区13793833513: matlab中,怎么完成对二进制数据的读取? -
上曼凡林: 1. 使用导入模板读取二进制数据 要使用导入模板来读取二进制数据,需按以下步骤进行:(1) 选择File→Import Data选项,弹出一个文件选择对话框;也可以使用uiimport函数来打开导入数据模板.(2) 在文件选择对话框中选择想导入数据的二...

庐山区13793833513: matlab 二进制格式文件输出 -
上曼凡林: 编写如下: % deal data from specified data file clear ; data_fname = 'data.dat' ; % 这里是文件名 jump_distance = 2048 ; % 这里是跳过的字节数 % 打开方式为二进制打开,其实'r'就行,matlab是默认二进制形式打开文件的 file_id = fopen(data_...

庐山区13793833513: 如何使用Matlab将txt中的许多2进制数转换为10进制数 -
上曼凡林: a=textread('c:\a.txt','%s')';%以字符形式打开文件 alpha=hex2dec(a)'; %16进制转化为10进制数,存入alpha矩阵 dlmwrite('c:\b.txt',alpha,'delimiter', ' ') %将得出数据存入新的b.txt文档 你可以参考一下啊.很容易的哈.

庐山区13793833513: awk命令怎么处理特殊字符 -
上曼凡林: 0x0A0D ,写成两个十六进制应该颠倒次序:RS="\x0D\x0A" 这和数据存放的高位、底位有关,对应的字符就是\r\n,也就是通常说的Windows/DOS下面的回车换行符 测试:或

庐山区13793833513: Matlab中如何实现二进制文件的读写 -
上曼凡林: 1)写二进制文件 fwrite函数按照指定的数据精度将矩阵中的元素写入到文件中.其调用格式为: COUNT=fwrite(fid,A,'precision') 说明:其中COUNT返回所写的数据元素个数(可缺省),fid为文件句柄,A用来存放写入文件的数据,precision代...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网