ホームページ バックエンド開発 Python チュートリアル Linuxコマンドxxd -iの機能紹介をPythonで実装

Linuxコマンドxxd -iの機能紹介をPythonで実装

Mar 07, 2017 pm 03:58 PM

1. Linux xxd -i 関数

Linux システムの xxd コマンドは、ファイルの内容をバイナリまたは 16 進形式で表示します。 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」を表すことに注意してください。

II. xxd -i

の一般的な使用法 デバイスにファイル システムがない場合、または動的メモリ管理をサポートしていない場合、バイナリ ファイル (ブートローダーやファームウェアなど) の内容が保存されることがあります。 C コードの静的配列。現時点では、xxd コマンドを使用してバージョン配列を自動的に生成できます。例:

1) Linux コマンド xdd を使用して、バイナリ ファイル VdslBooter.bin を 16 進ファイル DslBooter.txt に変換します。

xxd -i < VdslBooter.bin > ここで、 '- 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 前処理ディレクティブをうまく使用すると、配列の内容を手動でコピーする手間を回避できます。

3. 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__ == &#39;__main__&#39;:
print IsCKeywords(&#39;const&#39;)
#Xxdi()
ログイン後にコピー

このコードは、指定された文字列が C 言語のキーワードであるかどうかを判断します。 Windows システムの cmd コマンド プロンプトで「E:PyTest>python xxdi.py」と入力すると、実行結果は True になります。

次のコード スニペットでは、先頭のスクリプトとエンコーディングの宣言と、最後の「main」セクションが省略されています。

C 配列を生成する前に、配列名が有効であることを確認してください。 C 言語の識別子は文字、数字、アンダースコアのみで構成でき、数字で始めることはできません。また、キーワードを識別子として使用することはできません。不正な文字はすべて処理する必要があります。ルールについてはコード コメントを参照してください:

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

print GenerateCArrayName('1a$if1#1_4.txt') で実行すると、入力パラメータ文字列が変換されます。 __1a_if1_1_4_txt に。同様に、_Bool は _BOOL_ に変換されます。

Linux コマンド スタイルを可能な限りシミュレートするには、コマンド ライン オプションとパラメーターを指定する必要があります。解析モジュールは、optionparser を使用します。その使用法の詳細については、「Python コマンド ライン解析」を参照してください。 xxd -i-like 関数のコマンドライン実装は次のとおりです:

#def ParseOption(base, cols, strip, inFile, outFile):
def ParseOption(base = 16, cols = 12, strip = False, inFile = &#39;&#39;, outFile = None):
from optparse import OptionParser
custUsage = &#39;\n xxdi(.py) [options] inFile [outFile]&#39;
parser = OptionParser(usage=custUsage)
parser.add_option(&#39;-b&#39;, &#39;--base&#39;, dest=&#39;base&#39;,
help=&#39;represent values according to BASE(default:16)&#39;)
parser.add_option(&#39;-c&#39;, &#39;--column&#39;, dest=&#39;col&#39;,
help=&#39;COL octets per line(default:12)&#39;)
parser.add_option(&#39;-s&#39;, &#39;--strip&#39;, action=&#39;store_true&#39;, dest=&#39;strip&#39;,
help=&#39;only output C array elements&#39;)
(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 &#39;No argument, at least one(inFile)!\nUsage:%s&#39; %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 = &#39;&#39;; outFile = &#39;&#39;
([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 &#39;&#39;&#39;&#39;%s&#39; is not a file!&#39;&#39;&#39; %inFile
return
with open(inFile, &#39;rb&#39;) as file: #必须以&#39;b&#39;模式访问二进制文件
#file = open(inFile, &#39;rb&#39;) #Python2.5以下版本不支持with...as语法
#if True:
#不用for line in file或readline(s),以免遇&#39;0x0a&#39;换行
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 &#39;[%s]: Invalid base or radix for C language!&#39; %base
return
#构造数组定义头及长度变量
cArrayName = GenerateCArrayName(inFile)
if strip is False:
cArrayHeader = &#39;unsigned char %s[] = {&#39; %cArrayName
else:
cArrayHeader = &#39;&#39;
cArrayTailer = &#39;};\nunsigned int %s_len = %d;&#39; %(cArrayName, len(content))
if strip is True: cArrayTailer = &#39;&#39;
#print会在每行输出后自动换行
if outFile is None:
print cArrayHeader
for i in range(0, len(content), cols):
line = &#39;, &#39;.join(content[i:i+cols])
print &#39; &#39; + line + &#39;,&#39;
print cArrayTailer
return
with open(outFile, &#39;w&#39;) as file:
#file = open(outFile, &#39;w&#39;) #Python2.5以下版本不支持with...as语法
#if True:
file.write(cArrayHeader + &#39;\n&#39;)
for i in range(0, len(content), cols):
line = reduce(lambda x,y: &#39;, &#39;.join([x,y]), content[i:i+cols])
file.write(&#39; %s,\n&#39; %line)
file.flush()
file.write(cArrayTailer)
ログイン後にコピー

Python 2.5 より前のバージョンは with..as 構文をサポートしておらず、作者がデバッグに使用している Linux システムには Python2.4.3 のみがインストールされています。したがって、Linux システムで xddi.py を実行するには、 file = open(.... と記述するだけです。ただし、これには、ファイルのクローズと例外の処理が必要です。詳細については、「with...as... の理解」を参照してください。 Python の構文。5 で with...as 構文を使用する場合は、__future__ import with_statement を宣言する必要があります。例:

import platform
#判断Python是否为major.minor及以上版本
def IsForwardPyVersion(major, minor):
#python_version()返回&#39;major.minor.patchlevel&#39;,如&#39;2.7.11&#39;
ver = platform.python_version().split(&#39;.&#39;)
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 など)。もちろん、これらの欠点を解消するのは難しいことではありません。たとえば、出力ビット幅を制御するには、hex(val) の代わりに '0x%02x'%val を使用します。ただし、追加の改善によりコードの複雑さは必然的に増加し、その結果、労力が半分で済む可能性があります。

上記は編集者が紹介したLinuxコマンドxxd -i関数のPython実装です。皆さんの参考になれば幸いです。

Linux コマンド xxd -i 関数の Python 実装の紹介に関するその他の関連記事については、PHP 中国語 Web サイトに注目してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

LinuxターミナルでPythonバージョンを表示するときに発生する権限の問題を解決する方法は? LinuxターミナルでPythonバージョンを表示するときに発生する権限の問題を解決する方法は? Apr 01, 2025 pm 05:09 PM

LinuxターミナルでPythonバージョンを表示する際の許可の問題の解決策PythonターミナルでPythonバージョンを表示しようとするとき、Pythonを入力してください...

あるデータフレームの列全体を、Python内の異なる構造を持つ別のデータフレームに効率的にコピーする方法は? あるデータフレームの列全体を、Python内の異なる構造を持つ別のデータフレームに効率的にコピーする方法は? Apr 01, 2025 pm 11:15 PM

PythonのPandasライブラリを使用する場合、異なる構造を持つ2つのデータフレーム間で列全体をコピーする方法は一般的な問題です。 2つのデータがあるとします...

プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は? プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は? Apr 02, 2025 am 07:18 AM

10時間以内にコンピューター初心者プログラミングの基本を教える方法は?コンピューター初心者にプログラミングの知識を教えるのに10時間しかない場合、何を教えることを選びますか...

uvicornは、serving_forever()なしでhttpリクエストをどのように継続的に聞いていますか? uvicornは、serving_forever()なしでhttpリクエストをどのように継続的に聞いていますか? Apr 01, 2025 pm 10:51 PM

UvicornはどのようにしてHTTPリクエストを継続的に聞きますか? Uvicornは、ASGIに基づく軽量のWebサーバーです。そのコア機能の1つは、HTTPリクエストを聞いて続行することです...

文字列を介してオブジェクトを動的に作成し、Pythonでメソッドを呼び出す方法は? 文字列を介してオブジェクトを動的に作成し、Pythonでメソッドを呼び出す方法は? Apr 01, 2025 pm 11:18 PM

Pythonでは、文字列を介してオブジェクトを動的に作成し、そのメソッドを呼び出す方法は?これは一般的なプログラミング要件です。特に構成または実行する必要がある場合は...

人気のあるPythonライブラリとその用途は何ですか? 人気のあるPythonライブラリとその用途は何ですか? Mar 21, 2025 pm 06:46 PM

この記事では、numpy、pandas、matplotlib、scikit-learn、tensorflow、django、flask、and requestsなどの人気のあるPythonライブラリについて説明し、科学的コンピューティング、データ分析、視覚化、機械学習、Web開発、Hの使用について説明します。

中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか? 中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか? Apr 02, 2025 am 07:15 AM

fiddlereveryversings for the-middleの測定値を使用するときに検出されないようにする方法

See all articles