3

正規表現マッチングに Boost lib を使用しています。
検索したい入力「文字列」は、実際には文字列ではなく、任意のバイトを含むビットマップです。

入力文字列内に Null バイトがない限り、マッチングは正常に機能します。Null バイトがある場合、それ以降はすべて無視されます。

null バイトを置き換えると、このコードは機能します。

char* expr = ".*\\x08\\x00\\x27\\x47\\x6b\\xd4.*"
char data[] = {0x12, 0x08, 0x00, 0x27, 0x47, 0x6b, 0xd4, 0x08 }
boost::regex regex = boost::regex(expr);
boost::cmatch what;
if(boost::regex_match(data, what, regex)) 
  //found match
  ... 
else 
  // failure did not match
  ...

これを修正する方法を知っている人はいますか?

4

2 に答える 2

3

配列をnullで終わる文字列としてregex_match()扱い、 . null ターミネータを持たない型でも機能します。その方法でデータを表現しようとしましたか?char0x00regex_match()std::string

于 2012-12-18T19:42:42.967 に答える
1

Boost Regex は、バイナリ テキスト内のバイナリ パターンの照合にも使用できます。ゼロバイトのような制御文字と混同されません。

コンストラクターと関数にはいくつかのオーバーロードがあります。たとえば、、null 終わる C 文字列、および反復子範囲のオーバーロードです。boost::regexboost::regex_matchstd::string

0 バイトにも一致させたいので、明らかに null で終わる C 文字列を使用することはできません。使用std::stringは可能です (ゼロ バイトが含まれている可能性があるため) - ただし、検索のためだけにパターンとテキストをコピーするのは無駄です。

イテレータ範囲は、このユースケースに最適です。

例:

#include <iostream>
#include <boost/regex.hpp>
using namespace std;

int main(int argc, char **argv)
{   
  const unsigned char expr[] = {
    '.', '*', 0x08, 0x00, 0x27, 0x47, 0x6b, 0xd4, '.', '*' } ;
  const unsigned char data[] = {
    0x12, 0x08, 0x00, 0x27, 0x47, 0x6b, 0xd4, 0x08 };
  boost::regex regex(reinterpret_cast<const char*>(expr),
      reinterpret_cast<const char*>(expr) + sizeof expr);
  boost::cmatch what;
  if (boost::regex_match(reinterpret_cast<const char*>(data),
        reinterpret_cast<const char*>(data) + sizeof data, what, regex))
    cout << "match!\n";
  else 
    cout << "no match\n";
  return 0;
}

たとえば、次の方法でコンパイルします。

$ g++ regex.cc -o regex -Wall -g -lboost_regex

出力例:

$ ./regex
match!

sはreinterpret_cast危険に見えるかもしれませんが、それはすべて定義された動作です。data配列を配列として定義することはcharお勧めできません。アーキテクチャによっては char が符号付きまたは符号なしの場合があるためです。署名すると、次の0xd4エラーが発生します。

error: narrowing conversion of ‘212’ from ‘int’ to ‘char’ 
  inside { } [-Wnarrowing]

"\xd4"文字列リテラルのようなものを使用しようとすると、同様の問題が予想されます。二重のバックスラッシュを使用すると、エスケープは次のように簡単に混乱する Boost 正規表現によって解釈されます:「16 進エスケープ シーケンスが途中で終了しました」。

したがって、例のように unsigned char 配列を使用するのが最も簡単な解決策です。

于 2017-05-13T19:20:33.180 に答える