ファイル内の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進文字。\xAB
PCREです通事論16進数(10進数171)で、コードポイント値0xABの文字を一致させます。
コードポイントこれは、UTF-8を使用するロケールのUnicodeコードポイントであり、シングルバイト文字セットを使用するロケールのバイト値です(GNUはgrep -P
UTF-8以外のマルチバイト文字セットをサポートしません)。
したがって、\xAB
UTF-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システムに移植されたかどうかはわかりません。
答え2
ワイルドカードを使用する代わりに、次のようにすべてのASCII文字に一致する範囲を含めることができます。
grep -Pe '\x00\x50\x53\x46[\x00-\x7F]\x01\x00\x00\x34\x01\x00\x00'