ワイルドカードを使用して16進パターンを見つける方法は?

ワイルドカードを使用して16進パターンを見つける方法は?

ファイル内の16進パターンのオフセットを見つけようとしています。これは特定の値に対して機能します。

$ grep -obUaP -m1 "\x00\x50\x53\x46\x01\x01\x00\x00\x34\x01\x00\x00" file.bin
3088:PSF4

ただし、このパターンには変更されるバイト数が含まれているため、grepにワイルドカードを含める必要があります。私は何をすべきかわかりません。これまでに試したことはすべて次のとおりです。

  • \x.., \x., ..,私が考えることができるすべての同様の形式は一致しません。
  • \x[0-9][0-9]矛盾
  • \x.*矛盾
  • ただ.*(つまり、\x00.*\x01するマッチしますが、貪欲でパターンマッチング以上の機能を実行します。

おそらく愚かなことを見過ごしているかもしれませんが、ここで壁にぶつかりました。

16進ワイルドカードをどのように指定するのですか、それとも少なくともgrepとperl-regexを使用して16進数を検索するのですか?

ベストアンサー1

grep -P '\xAB'探していない16進文字。そのようなことはありません16進文字\xABPCREです通事論16進数(10進数171)で、コードポイント値0xABの文字を一致させます。

コードポイントこれは、UTF-8を使用するロケールのUnicodeコードポイントであり、シングルバイト文字セットを使用するロケールのバイト値です(GNUはgrep -PUTF-8以外のマルチバイト文字セットをサポートしません)。

したがって、\xABUTF-8ロケール(2バイト:0xc2および0xabでエンコードされている)のU + 00AB文字(<)とシングルバイトロケールの0xABバイト(たとえばЋiso8859-5を使用することを意味)と一致します。文字セット)。

バイト値を一致させるには、ロケールがシングルバイト文字セットを使用していることを確認する必要があります。Cロケールが最善の方法でしょう。

LC_ALL=C grep -P '\xAB'

文字セットで表される文字(存在する場合)に関係なく、0xAB(171)バイトと一致します。

単一バイトを一致させるために再利用できます.(Cロケールまたは文字セットが1文字あたり1バイトのローカル言語を想定しています)。

@Angle115がすでに述べたように、バイト値の範囲と一致します。 ([\x01-\x45]これは1から0x45/69までのバイト値に適用されます。)

しかし覚えて、grepマッチングコンテンツテキストワイヤー¹なので、改行文字は行区切り文字として検索されず、その値はロケールに関係なく常に0x0A²(10進数10)です。

したがって、LC_ALL=C grep -P '\x23.\xab'3バイトのシーケンスが一致し、最初のバイトの値は0x23で、2番目のバイトの値はany valueです。0xAを除く3番目の値は0xABです。

任意の値(0xAを含む)を持つバイトを取得するには、以前と同じように一度に1行ずつ処理したり、NULL区切りレコードを処理したりするのではなく、入力全体を完全に処理する必要がありますgrep

これを行うには、フラグ(新しい行は特に処理されません)またはフルルックモードで(複数行)オプションをpcregrep使用できます。-M(?s).perl

LC_ALL=C pcregrep --file-offsets -Ma '(?s)\x23.\xab' < file

(オプションがpcregrepない場合は、オフセットと長さをできるだけ近く印刷します。)-b--file-offsets

perl -l -0777 -ne 'print "$-[0]:$_" while /\x23.\xab/gs' < file

または:

perl -l -0777 -ne 'print $-[0] if /\x23.\xab/s' < file

一致する最初のバイトオフセットのみが印刷されます。

perlファイル全体をメモリにロードすることはpcregrepできませんが、0xA バイト離れたファイルを処理できないという内部制限があります。


--null¹または/で区切られたNULレコード-z

¹ASCIIベースのシステムで。私はlibpcreがEBCDICシステムに移植されたかどうかはわかりません。

おすすめ記事