iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >Python实现Linux命令xxd -i功能
  • 517
分享到

Python实现Linux命令xxd -i功能

命令功能Python 2022-06-04 19:06:57 517人浏览 八月长安
摘要

一. Linux xxd -i功能 linux系统xxd命令使用二进制或十六进制格式显示文件内容。若未指定outfile参数,则将结果显示在终端屏幕上;否则输出到outfile中。详细的

一. Linux xxd -i功能

linux系统xxd命令使用二进制或十六进制格式显示文件内容。若未指定outfile参数,则将结果显示在终端屏幕上;否则输出到outfile中。详细的用法可参考linux命令xxd。

本文主要关注xxd命令-i选项。使用该选项可输出以inputfile为名的C语言数组定义。例如,执行echo 12345 > test和xxd -i test命令后,输出为:


unsigned char test[] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x0a
};
unsigned int test_len = 6;

可见,数组名即输入文件名(若有后缀名则点号替换为下划线)。注意,0x0a表示换行符LF,即'n'。

二. xxd -i常见用途

当设备没有文件系统或不支持动态内存管理时,有时会将二进制文件(如引导程序和固件)内容存储在C代码静态数组内。此时,借助xxd命令就可自动生成版本数组。举例如下:

1) 使用Linux命令xdd将二进制文件VdslBooter.bin转换为16进制文件DslBooter.txt:

xxd -i < VdslBooter.bin > DslBooter.txt

其中,'-i'选项表示输出为C包含文件的风格(数组方式)。重定向符号'<'将VdslBooter.bin文件内容重定向到标准输入,该处理可剔除数组声明和长度变量定义,使输出仅包含16进制数值。

2) 在C代码源文件内定义相应的静态数组:


static const uint8 bootImageArray[] = {
#include " ../../DslBooter.txt"
};
TargetImage bootImage = {
(uint8 *) bootImageArray,
sizeof(bootImageArray) / sizeof(bootImageArray[0])
};

编译源码时,DslBooter.txt文件的内容会自动展开到上述数组内。通过巧用#include预处理指令,可免去手工拷贝数组内容的麻烦。

三. 类xxd -i功能的python实现

本节将使用Python2.7语言实现类似xxd -i的功能。

因为作者处于学习阶段,代码中存在许多写法不同但功能相同或相近的地方,旨在提供不同的语法参考,敬请谅解。

首先,请看一段短小却完整的程序(保存为xddi.py):


#!/usr/bin/python
#coding=utf-8
#判断是否C语言关键字
CKeyWords = ("auto", "break", "case", "char", "const", "continue", "default",
"do","double","else","enum","extern","float","for",
"Goto","if","int","long","reGISter","return","short",
"signed","static","sizeof","struct","switch","typedef","uNIOn",
"unsigned","void","volatile","while", "_Bool") #_Bool为C99新关键字
def IsCKeywords(name):
for x in CKeywords:
if cmp(x, name) == 0:
return True
return False
if __name__ == '__main__':
print IsCKeywords('const')
#Xxdi()

这段代码判断给定的字符串是否为C语言关键字。在windows系统cmd命令提示符下输入E:PyTest>python xxdi.py,执行结果为True。

接下来的代码片段将省略头部的脚本和编码声明,以及尾部的'main'段。

生成C数组前,应确保数组名合法。C语言标识符只能由字母、数字和下划线组成,且不能以数字开头。此外,关键字不能用作标识符。所有,需要对非法字符做处理,其规则参见代码注释:


import re
def GenerateCArrayName(inFile):
#字母数字下划线以外的字符均转为下划线
#'int $=5;'的定义在GCc 4.1.2可编译通过,但此处仍视为非法标识符
inFile = re.sub('[^0-9a-zA-Z_]', '_', inFile) #'_'改为''可剔除非法字符
#数字开头加双下划线
if inFile[0].isdigit() == True:
inFile = '__' + inFile
#若输入文件名为C语言关键字,则将其大写并加下划线后缀作为数组名
#不能仅仅大写或加下划线前,否则易于用户自定义名冲突
if IsCKeywords(inFile) is True:
inFile = '%s_' %inFile.upper()
return inFile

以print GenerateCArrayName('1a$if1#1_4.txt')执行时,入参字符串将被转换为__1a_if1_1_4_txt。类似地,_Bool被转换为_BOOL_。

为了尽可能模拟Linux命令风格,还需提供命令行选项和参数。解析模块选用optionparser,其用法详见python命令行解析。类xxd -i功能的命令行实现如下:


#def ParseOption(base, cols, strip, inFile, outFile):
def ParseOption(base = 16, cols = 12, strip = False, inFile = '', outFile = None):
from optparse import OptionParser
custUsage = 'n xxdi(.py) [options] inFile [outFile]'
parser = OptionParser(usage=custUsage)
parser.add_option('-b', '--base', dest='base',
help='represent values according to BASE(default:16)')
parser.add_option('-c', '--column', dest='col',
help='COL octets per line(default:12)')
parser.add_option('-s', '--strip', action='store_true', dest='strip',
help='only output C array elements')
(options, args) = parser.parse_args()
if options.base is not None:
base = int(options.base)
if options.col is not None:
cols = int(options.col)
if options.strip is not None:
strip = True
if len(args) == 0:
print 'No argument, at least one(inFile)!nUsage:%s' %custUsage
if len(args) >= 1:
inFile = args[0]
if len(args) >= 2:
outFile = args[1]
return ([base, cols, strip], [inFile, outFile])

被注释掉的def ParseOption(...)原本是以下面的方式调用:


base = 16; cols = 12; strip = False; inFile = ''; outFile = ''
([base, cols, strip], [inFile, outFile]) = ParseOption(base,
cols, strip, inFile, outFile)

其意图是同时修改base、cols、strip等参数值。但这种写法非常别扭,改用缺省参数的函数定义方式,调用时只需要写ParseOption()即可。若读者知道更好的写法,望不吝赐教。

以-h选项调出命令提示,可见非常接近Linux风格:


E:PyTest>python xxdi.py -h
Usage:
xxdi(.py) [options] inFile [outFile]
Options:
-h, --help show this help message and exit
-b BASE, --base=BASE represent values according to BASE(default:16)
-c COL, --column=COL COL octets per line(default:12)
-s, --strip only output C array elements

基于上述练习,接着完成本文的重头戏:


def Xxdi():
#解析命令行选项及参数
([base, cols, strip], [inFile, outFile]) = ParseOption()
import os
if os.path.isfile(inFile) is False:
print ''''%s' is not a file!''' %inFile
return
with open(inFile, 'rb') as file: #必须以'b'模式访问二进制文件
#file = open(inFile, 'rb') #Python2.5以下版本不支持with...as语法
#if True:
#不用for line in file或readline(s),以免遇'0x0a'换行
content = file.read()

#将文件内容"打散"为字节数组
if base is 16: #Hexadecimal
content = map(lambda x: hex(ord(x)), content)
elif base is 10: #Decimal
content = map(lambda x: str(ord(x)), content)
elif base is 8: #Octal
content = map(lambda x: oct(ord(x)), content)
else:
print '[%s]: Invalid base or radix for C language!' %base
return
#构造数组定义头及长度变量
cArrayName = GenerateCArrayName(inFile)
if strip is False:
cArrayHeader = 'unsigned char %s[] = {' %cArrayName
else:
cArrayHeader = ''
cArrayTailer = '};nunsigned int %s_len = %d;' %(cArrayName, len(content))
if strip is True: cArrayTailer = ''
#print会在每行输出后自动换行
if outFile is None:
print cArrayHeader
for i in range(0, len(content), cols):
line = ', '.join(content[i:i+cols])
print ' ' + line + ','
print cArrayTailer
return
with open(outFile, 'w') as file:
#file = open(outFile, 'w') #Python2.5以下版本不支持with...as语法
#if True:
file.write(cArrayHeader + 'n')
for i in range(0, len(content), cols):
line = reduce(lambda x,y: ', '.join([x,y]), content[i:i+cols])
file.write(' %s,n' %line)
file.flush()
file.write(cArrayTailer)

Python2.5以下版本不支持with...as语法,而作者调试所用的Linux系统仅装有Python2.4.3。因此,要在Linux系统中运行xddi.py,只能写为file = open(...。但这需要处理文件的关闭和异常,详见理解Python中的with…as…语法。注意,Python2.5中使用with...as语法时需要声明from __future__ import with_statement。

可通过platfORM.python_version()获取Python版本号。例如:


import platform
#判断Python是否为major.minor及以上版本
def IsForwardPyVersion(major, minor):
#python_version()返回'major.minor.patchlevel',如'2.7.11'
ver = platform.python_version().split('.')
if int(ver[0]) >= major and int(ver[1]) >= minor:
return True
return False

经过Windows和Linux系统双重检验后,Xddi()工作基本符合预期。以123456789ABCDEF.txt文件(内容为'123456789ABCDEF')为例,测试结果如下:


E:PyTest>python xxdi.py -c 5 -b 2 -s 123456789ABCDEF.txt
[2]: Invalid base or radix for C language!
E:Pytest>python xxdi.py -c 5 -b 10 -s 123456789ABCDEF.txt

49, 50, 51, 52, 53,
54, 55, 56, 57, 65,
66, 67, 68, 69, 70,
E:PyTest>python xxdi.py -c 5 -b 10 123456789ABCDEF.txt
unsigned char __123456789ABCDEF_txt[] = {
49, 50, 51, 52, 53,
54, 55, 56, 57, 65,
66, 67, 68, 69, 70,
};
unsigned int __123456789ABCDEF_txt_len = 15;
E:PyTest>python xxdi.py -c 5 -b 8 123456789ABCDEF.txt
unsigned char __123456789ABCDEF_txt[] = {
061, 062, 063, 064, 065,
066, 067, 070, 071, 0101,
0102, 0103, 0104, 0105, 0106,
};
unsigned int __123456789ABCDEF_txt_len = 15;
E:PyTest>python xxdi.py 123456789ABCDEF.txt
unsigned char __123456789ABCDEF_txt[] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46,
};
unsigned int __123456789ABCDEF_txt_len = 15;

再以稍大的二级制文件为例,执行 python xxdi.py VdslBooter.bin booter.c后,booter.c文件内容如下(截取首尾):


unsigned char VdslBooter_bin[] = {
0xff, 0x31, 0x0, 0xb, 0xff, 0x3, 0x1f, 0x5a, 0x0, 0x0, 0x0, 0x0,
//... ... ... ...
0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
unsigned int VdslBooter_bin_len = 53588;

综上可见,作者实现的xxdi模块与Linux xxd -i功能非常接近,且各有优劣。xxdi优点在于对数组名合法性校验更充分(关键字检查),数组内容表现形式更丰富(8进制和10进制);缺点在于不支持重定向,且数值宽度不固定(如0xb和0xff)。当然,这些缺点并不难消除。例如,用'0x%02x'%val代替hex(val)即可控制输出位宽。只是,再加完善难免提高代码复杂度,也许会事倍功半。

以上所述是小编给大家介绍的Python实现Linux命令xxd -i功能,希望对大家以上帮助!

--结束END--

本文标题: Python实现Linux命令xxd -i功能

本文链接: https://www.lsjlt.com/news/15249.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python实现tail -f命令功能
    #!/usr/bin/env python #!encoding:utf-8 ''' Python-Tail - Unix tail follow implementation in Python. python-tail can be...
    99+
    2023-01-31
    命令 功能 python
  • 使用Python实现touch命令功能
           公司指定的办公平台是Windows,而且给了诸多不自由的限制。如果对shell有一点点依赖,那么会是一个很麻烦的事情,毕竟对Windows的批处理命令熟悉度不够。由于touch命令使用的频繁,我觉得可以拿Python去模拟一...
    99+
    2023-01-31
    命令 功能 Python
  • Rundll.exe 多功能实现命令
    首先,请你做个小实验(请事先保存好你正在执行的程式的结果)∶点击“开始-程式-Ms-DOS方式”,进入Dos视窗,然後键入“rundll32.exe user.exe,restartW...
    99+
    2023-05-24
    Rundll.exe 多功能 命令 Rundll
  • python实现Linux命令wget
    #!/bin/python #coding:utf-8 def wget(url,new_name=""): ''' wget封装,需提供下载地址,新文件名参数可省略 ...
    99+
    2023-01-31
    命令 python Linux
  • linux vmstat命令有哪些功能
    vmstat命令用于显示系统的虚拟内存情况,包括虚拟内存的使用情况、磁盘I/O、CPU利用率等信息。其主要功能包括: 显示系统的虚...
    99+
    2024-03-01
    linux
  • Rundll.exe 多功能实现命令的示例
    这篇文章主要介绍Rundll.exe 多功能实现命令的示例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!首先,请你做个小实验(请事先保存好你正在执行的程式的结果)∶点击“开始-程式-Ms-Dos方式”,进入Dos视窗...
    99+
    2023-06-14
  • Linux history命令有哪些功能
    Linux的history命令主要有以下几个功能:1. 查看历史命令列表:使用history命令可以查看当前用户执行过的所有命令的列...
    99+
    2023-09-15
    Linux
  • Golang实现简易的命令行功能
    目录前言开始flag.Stringflag.Intflag.StringVarflag.IntVar定义命令行参数实现 -f -v 是否强制拷贝copyFileAction 实现co...
    99+
    2023-02-13
    Golang实现命令行功能 Golang命令行功能 Golang命令行
  • linux中怎么利用ntp命令实现时间同步功能
    这篇文章给大家介绍linux中怎么利用ntp命令实现时间同步功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如果服务器的时间出现混乱,将导致很多意想不到的问题。使用NTP,可以使服务器获取正确的时间,从而避免出现问题...
    99+
    2023-06-13
  • linux的sudo命令有哪些功能
    这篇文章主要介绍“linux的sudo命令有哪些功能”,在日常操作中,相信很多人在linux的sudo命令有哪些功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux的sudo命令有哪些功能”的疑惑有所...
    99+
    2023-06-06
  • linux中partprobe命令有什么功能
    partprobe命令用于通知操作系统重新扫描磁盘分区表,以识别最新的分区信息。具体功能如下:1. 更新内核中的分区表信息:当在磁盘...
    99+
    2023-09-04
    linux partprobe
  • Linux C/C++ timeout命令实现运行具有时间限制功能
    目录Linux C/C++ timeout命令实现运行具有时间限制如何使用timeout命令如何使用timeout命令的基本示例1.设置定时间后终止命令:2.发送正确的信号3.尝试使...
    99+
    2023-02-14
    Linux运行具有时间限制 C++ timeout命令
  • Linux/Unix的find命令的主要功能
    本篇内容主要讲解“Linux/Unix的find命令的主要功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux/Unix的find命令的主要功能”吧!主要功能如下(所有测试均在当前目录(...
    99+
    2023-06-05
  • linux中ll命令的功能有哪些
    显示文件的详细信息,包括文件权限、所有者、所属组、大小、修改日期等。 将文件按照大小、时间等属性进行排序显示。 显示文件的大小以更...
    99+
    2024-03-04
    linux
  • linux中init命令的功能有哪些
    在Linux中,init命令的功能主要有以下几个方面: 启动系统:init命令是Linux系统的第一个进程,它负责启动系统的所有...
    99+
    2024-03-04
    linux
  • Linux top命令的常用快捷键功能
    这篇文章主要介绍“Linux top命令的常用快捷键功能”,在日常操作中,相信很多人在Linux top命令的常用快捷键功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux top命令的常用快捷键功能...
    99+
    2023-06-16
  • Go语言中怎么实现tail命令的功能
    这篇文章主要讲解了“Go语言中怎么实现tail命令的功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言中怎么实现tail命令的功能”吧!在 Go 语言中,我们可以使用 os 包和 b...
    99+
    2023-07-06
  • 怎么用vbs实现cmd多命令运行功能
    这篇文章主要讲解了“怎么用vbs实现cmd多命令运行功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用vbs实现cmd多命令运行功能”吧!on error resu...
    99+
    2023-06-09
  • php如何实现linux命令
    这篇文章主要为大家展示了“php如何实现linux命令”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“php如何实现linux命令”这篇文章吧。php实现linux命令的方法:1、创建一个PHP示...
    99+
    2023-06-21
  • linux shell历史命令记录功能如何用
    本篇内容主要讲解“linux shell历史命令记录功能如何用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux shell历史命令记录功能如何用”吧!在 linux 下面可以使用 his...
    99+
    2023-07-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作