3

我正在使用 Boost lib 进行正则表达式匹配。
我要在其中搜索的输入“字符串”实际上不是字符串,而是位图,它可能包含任何字节。

只要输入字符串中没有空字节,匹配就可以正常工作。如果存在 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

听起来像是regex_match()将您的char数组视为以空字符结尾的字符串,并将所有内容都输入到0x00. regex_match()也适用于std::string没有空终止符的类型。您是否尝试过以这种方式表示您的数据?

于 2012-12-18T19:42:42.967 回答
1

Boost Regex 也可用于匹配二进制文本中的二进制模式。它不会被零字节等控制字符混淆。

构造函数和函数有几个 重载,例如那些采用 a ,一个以空结尾的 C 字符串 - 和 - 用于迭代器范围的重载。boost::regexboost::regex_matchstd::string

由于我们还想匹配零字节,我们显然不能使用以空结尾的 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 正则表达式解释,它很容易像这样混淆:“十六进制转义序列过早终止”。

因此,仅使用示例中的无符号字符数组是最简单的解决方案。

于 2017-05-13T19:20:33.180 回答