从std :: regex中提取原始正则表达式模式

ine*_*ght 13 c++ regex string c++11

我有一个函数,它试图将给定的字符串与给定的正则表达式模式匹配.如果它不匹配,它应该创建一个指示这种情况的字符串,并包括它失败的正则表达式模式和字符串的内容.类似的东西:

bool validate_content(const std::string & str, const std::regex & pattern, std::vector<std::string> & errors)
{
    if ( false == std::regex_match(str, pattern) )
    {
        std::stringstream error_str;
        // error_str << "Pattern match failure: " << pattern << ", content: " << str;
        errors.push_back(error_str.str());
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但是正如您所看到的,注释掉的行提出了一个挑战:是否可以恢复正则表达式对象的原始模式?

显然有一种解决方法是提供原始模式字符串(而不是或旁边)正则表达式对象然后使用它.但是我当然希望不需要包含额外的工作来在每次调用此函数时重新创建正则表达式对象(每次调用函数时重新定位模式的成本)或者将正则表达式模式与正则表达式对象(容易出现拼写错误和错误,除非我提供一个包装器为我做这个,这不方便).

我在Ubuntu 14.04上使用GCC 4.9.2.

ric*_*ici 9

boost::basic_regex对象具有一个str()函数,该函数返回用于构造正则表达式的字符串的(副本).(他们还提供begin()end()它返回迭代器的字符序列,以及用于捕获内省的子表达式的机制接口.)

这些接口在最初的TR1正则表达式标准化提案中,但是在采用n1499:简化basic_regex中的接口之后于2003年被删除,我引用它:

basic_regex不应保留其初始化程序的副本

basic_regex模板有一个成员函数str返回保存用于初始化中的文本对象basic_regex的对象......虽然它可能偶尔会来看看初始化字符串是有用的,我们应该运用你不要,如果你为它付出的规则不要使用它.正如fstream对象不带有它们打开的文件名一样,basic_regex对象不应随身携带初始化文本.如果有人需要跟踪该文本,他们可以编写一个包含文本和basic_regex对象的类.

  • @CraigB:确实如此,但它是 C++ 正则表达式库历史的一部分。我认为 C++ 标准提案的摘录在其反应的背景下更有意义。(当然,你可能不同意。)而且,Boost 可能比尝试手卷包装纸更好。 (2认同)

101*_*010 6

根据标准N4431§28.8 / 2类模板basic_regex [re.regex](强调我的):

类型特化的对象basic_regex负责将charT对象序列转换为内部表示.未指定此表示形式采用何种形式,也未指定如何通过正则表达式操作的算法访问它.[ 注意:实现通常会声明一些函数模板作为basic_regex实现此目的的朋友- 结束语 ]

因此,basic_regex对象不需要在内部保留原始字符序列.

因此,您必须在创建时存储字符序列regex.例如:

struct RegexPattern {
  std::string pattern;
  std::regex  reg;
};
...
bool validate_content(const std::string & str, const RegexPattern & pattern, std::vector<std::string> & errors) {
    if(false == std::regex_match(str, pattern.reg)) {
        std::stringstream error_str;
        error_str << "Pattern match failure: " << pattern.pattern << ", content: " << str;
        errors.push_back(error_str.str());
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

@Praetorian提出的另一个更优雅的解决方案,但效率低一些(我没有对两个版本进行基准测试,因此我不确定).将保留模式字符串并将其作为输入参数传递给函数validate_content并在regex内部创建对象,如下所示:

bool validate_content(const std::string & str, const string & pattern, std::vector<std::string> & errors) {
    std::regex reg(pattern);
    if(false == std::regex_match(str, reg)) {
        std::stringstream error_str;
        error_str << "Pattern match failure: " << pattern << ", content: " << str;
        errors.push_back(error_str.str());
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

  • 这是完全有意义的事情之一,不应该改变,但只是_真的很烦人. (3认同)
  • 另一种选择,取决于`regex`模式是否需要在其他地方可用,将是`validate_content`采用包含模式的`std :: string`参数,并在本地构造`regex`. (2认同)
  • 很公平,如果它被召唤很多,那么我就不会这样做.:)无论哪种方式,我认为你在这里拥有你需要的一切.好极了! (2认同)