【问题标题】:Byte regex matching with Boost in C++字节正则表达式与 C++ 中的 Boost 匹配
【发布时间】:2012-12-18 19:15:23
【问题描述】:

我正在使用 Boost 库进行正则表达式匹配。
我要搜索的输入“字符串”实际上不是 一个字符串,但更多的是一个位图,可以包含任何字节。

只要没有匹配就可以正常工作 输入字符串中的空字节。如果有一个 空字节,它之后的所有内容都被忽略。

如果我替换空字节,此代码有效:

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
  ...

有人知道如何解决这个问题吗?

【问题讨论】:

  • 这看起来更像是固定字符串搜索,而不是正则表达式匹配。
  • 这只是为了证明概念,我真的很想将它用于正则表达式匹配......两种情况下都会出现错误。

标签: c++ regex boost match


【解决方案1】:

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

【讨论】:

  • 好主意,我会试试的!
  • 我刚尝试传递一个字符串,我得到以下错误:没有匹配函数调用'regex_match(std::string&, boost::cmatch&, boost::regex&)'。
  • ... 或者,如果您不想将数据放入 std::string 中,请使用采用一对迭代器而不是单个 char const * 参数的重载。您可以传递 data, data + sizeof(data) 作为迭代器来指定您的范围。
【解决方案2】:

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

several overloads 用于 boost::regex 构造函数和 boost::regex_match 函数,例如那些采用std::string,一个空终止的 C 字符串 - 和 - 迭代器范围的重载。

由于我们还想匹配零字节,我们显然不能使用以空值结尾的 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!

reinterpret_casts 可能看起来很危险,但它都是已定义的行为。请注意,将data 数组定义为char 数组并不是一个好主意,因为根据架构,char 可能是有符号或无符号的。当它被签名时,0xd4 会产生这个错误:

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

尝试在字符串文字中使用 "\xd4" 之类的内容时,预计会出现类似问题。使用双反斜杠转义由 Boost 正则表达式解释,它很容易像这样混淆:“十六进制转义序列过早终止”。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多