有时候需要查看一些二进制文件的内容,比如二进制文件中包含的某些字符串。这个时候可以用 hexdump 进行查看。
常用参数:
hexdump -C -n length -s skip file_name
-C 定义了导出的格式;-s skip 指定了从文件头跳过多少字节,或者说是偏移量,默认是十进制,如果是0x开头,则是十六进制;-n 指定了导出多少长度。
如果是寻找文本内容,则经常在后面用管道跟上grep命令:
hexdump -C file_name | grep hellokitty
这样就可以找到相关内容的偏移量,然后hexdump -C -n length -s skip file_name 查看文本附近的内容。
参考链接:http://blog.mchz.com.cn/?p=1408
用途说明
hexdump命令一般用来查看“二进制”文件的十六进制编码,但实际上它的用途不止如此,手册页上的说法是“ascii, decimal, hexadecimal, octal dump”,它能查看任何文件,而不只限于二进制文件。另外还有 xxd 和 od 也可以做类似的事情。在程序输出二进制格式的文件时,常用hexdump来检查输出是否正确。当然也可以使用Windows上的UltraEdit32之类的工具查看文件的十六进制编码,但Linux上有现成的工具,何不拿来用呢。
常用参数
如果要看到较理想的结果,推荐使用-C参数,显示结果分为三列(文件偏移量、字节的十六进制、ASCII字符)。
格式:hexdump -C binfile
一般文件都不是太小,最好用less来配合一下。
格式:hexdump -C binfile | less
示例一 比较各种参数的输出结果
[root@new55 ~]# echo /etc/passwd | hexdump 0000000 652f 6374 702f 7361 7773 0a64 000000c [root@new55 ~]# echo /etc/passwd | od -x 0000000 652f 6374 702f 7361 7773 0a64 0000014 [root@new55 ~]# echo /etc/passwd | xxd 0000000: 2f65 7463 2f70 6173 7377 640a /etc/passwd. [root@new55 ~]# echo /etc/passwd | hexdump -C <== 规范的十六进制和ASCII码显示(Canonical hex+ASCII display ) 00000000 2f 65 74 63 2f 70 61 73 73 77 64 0a |/etc/passwd.| 0000000c [root@new55 ~]# echo /etc/passwd | hexdump -b <== 单字节八进制显示(One-byte octal display) 0000000 057 145 164 143 057 160 141 163 163 167 144 012 000000c [root@new55 ~]# echo /etc/passwd | hexdump -c <== 单字节字符显示(One-byte character display) 0000000 / e t c / p a s s w d \n 000000c [root@new55 ~]# echo /etc/passwd | hexdump -d <== 双字节十进制显示(Two-byte decimal display) 0000000 25903 25460 28719 29537 30579 02660 000000c [root@new55 ~]# echo /etc/passwd | hexdump -o <== 双字节八进制显示(Two-byte octal display) 0000000 062457 061564 070057 071541 073563 005144 000000c [root@new55 ~]# echo /etc/passwd | hexdump -x <== 双字节十六进制显示(Two-byte hexadecimal display) 0000000 652f 6374 702f 7361 7773 0a64 000000c [root@new55 ~]# echo /etc/passwd | hexdump -v 0000000 652f 6374 702f 7361 7773 0a64 000000c
比较来比较去,还是hexdump -C选项的显示效果更好些。
示例二 确认文本文件的格式
文本文件在不同操作系统上的行结束标志是不一样的,经常会碰到由此带来的问题。比如Linux的许多命令不能很好的处理DOS格式的文本文件。Windows/DOS下的文本文件是以”\r\n”作为行结束的,而Unix/Linux下的文本文件是以”\n”作为行结束的。
[root@new55 ~]# cat test.bc 123*321 123/321 scale=4;123/321 [root@new55 ~]# hexdump -C test.bc 00000000 31 32 33 2a 33 32 31 0a 31 32 33 2f 33 32 31 0a |123*321.123/321.| 00000010 73 63 61 6c 65 3d 34 3b 31 32 33 2f 33 32 31 0a |scale=4;123/321.| 00000020 0a |.| 00000021 [root@new55 ~]# 注:常见的ASCII字符的十六进制表示 \r 0D \n 0A \t 09 DOS/Windows的换行符 \r\n 即十六进制表示 0D 0A Linux/Unix的换行符 \n 即十六进制表示 0A
参考链接:http://codingstandards.iteye.com/blog/805778
hexdump / xxd / od
系统自带都有,所以在Linux下做进制转换真的是太方便了。
注:三个命令都可以像UltraEdit那样以16进制的方式查看文件。hexdump的输出格式最灵活,因为它有专门的参数指定格式;不知道od的特点在哪,od -x 和不带选项的xxd差不多;xxd还可以通过-r选项把16进制表示的反转换为正常的文件,个人感觉xxd最“正常”,因为它默认的表示方式和UltraEdit最像:以位移开头,然后每两字节一组,每行最后有相应字节的文件显示。
http://hi.baidu.com/gsxwgtvhgabbjrq/item/3d4d771ad1c66d8b88a95681
hexdump的高级用法
-e 指定格式字符串,格式字符串包含在一对单引号中,格式字符串形如:
'a/b "format1" "format2"'
每个格式字符串由三部分组成,每个由空格分隔,第一个形如a/b,b表示对每b个输入字节应用format1格式,a表示每a个字节一组一起显示,另外a可以省略,省略则a=1。format1和format2中可以使用类似printf的格式字符串,如:
- %02d:两位十进制
- %03x:三位十六进制
- %02o:两位八进制
- %c:单个字符等
还有一些特殊的用法:
- %_ad:标记下一个输出字节的序号,用十进制表示
- %_ax:标记下一个输出字节的序号,用十六进制表示
- %_ao:标记下一个输出字节的序号,用八进制表示
- %_p:对不能以常规字符显示的用.代替
同一行如果要显示多个格式字符串,则可以跟多个-e选项
参考链接:
http://www.cnblogs.com/openix/archive/2012/03/19/2406568.html
显示每个字符对应的十进制、十六进制、八进制的Bash脚本
#!/bin/bash ASCII="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" echo $ASCII | hexdump -v -e '"%02_ad "' -e '1/1 "%1c "' -e '1/1 "hex=%02X "' -e '1/1 "dec=%3d "' -e '1/1 "oct=%03o\n"'
=EOF=
《 “使用hexdump查看二进制文件” 》 有 3 条评论
在终端中查看ASCII码表
`$ man ascii`
http://man7.org/linux/man-pages/man7/ascii.7.html
若出现`No manual entry for`的报错,则表示除了需要有man之外,还需要安装man-pages
`$ sudo yum install man man-pages`
如何在终端中打印出所有的可打印字符?
http://unix.stackexchange.com/questions/15139/how-to-print-all-printable-ascii-chars-in-cli
`
for((i=32;i<=127;i++)) do printf \$(printf '%03ot' "$i"); done;printf "n"
或
awk 'BEGIN{for(i=32;i<128;i++)printf "%c",i}';echo
`
hexyl – 一个命令行十六进制查看器
https://github.com/sharkdp/hexyl
Python中如何检测字符/字符串是否可打印字符?
Test if a python string is printable
https://stackoverflow.com/questions/3636928/test-if-a-python-string-is-printable/50731077#50731077
`
>>> hello = ‘Hello World!’
>>> bell = chr(7)
>>> import string
>>> all(c in string.printable for c in hello)
True
>>> all(c in string.printable for c in bell)
False
>>> printset = set(string.printable)
>>> helloset = set(hello)
>>> bellset = set(bell)
>>> helloset
set([‘!’, ‘ ‘, ‘e’, ‘d’, ‘H’, ‘l’, ‘o’, ‘r’, ‘W’])
>>> helloset.issubset(printset)
True
>>> set(bell).issubset(printset)
False
import string
printset = set(string.printable)
isprintable = set(yourstring).issubset(printset)
`