在 C++ 中用 "DEFINED" 子表达式组成复杂的正则表达式

Composing complex regular expressions with "DEFINED" subexpressions in C++

我正在尝试用 C++ 编写正则表达式来匹配 base64 编码的字符串。我非常熟悉在 Perl 中编写复杂的正则表达式,所以我从它开始:

use strict;
use warnings;

my $base64_regex = qr{
(?(DEFINE)
    (?<B64>[A-Za-z0-9+/])
    (?<B16>[AEIMQUYcgkosw048])
    (?<B04>[AQgw])
)
^(
    ((?&B64){4})*
    (
        (?&B64){4}|
        (?&B64){2}(?&B16)=|
        (?&B64)(?&B04)={2}
    )
)?$}x;

# "Hello World!" base64 encoded 
my $base64 = "SGVsbG8gV29ybGQh";

if ($base64 =~ $base64_regex)
{
    print "Match!\n";
}
else
{
    print "No match!\n"
}

输出:

Match!

然后我尝试用 C++ 实现一个类似的正则表达式:

#include <iostream>
#include <regex>

int main()
{
    std::regex base64_regex(
        "(?(DEFINE)"
            "(?<B64>[A-Za-z0-9+/])"
            "(?<B16>[AEIMQUYcgkosw048])"
            "(?<B04>[AQgw])"
        ")"
        "^("
            "((?&B64){4})*"
            "("
                "(?&B64){4}|"
                "(?&B64){2}(?&B16)=|"
                "(?&B64)(?&B04)={2}"
            ")"
        ")?$");

    // "Hello World!" base64 encoded 
    std::string base64 = "SGVsbG8gV29ybGQh";

    if (std::regex_match(base64, base64_regex))
    {
        std::cout << "Match!" << std::endl;
    }
    else
    {
        std::cout << "No Match!" << std::endl;
    }
}

但是当我 运行 代码时,我得到一个异常告诉我它不是一个有效的正则表达式。

捕获异常并打印“what”字符串也无济于事。它给我的是以下内容:

regex_error(error_syntax)

显然我可以用预定义的子模式摆脱“DEFINE”块,但这会使整个表达式很难阅读......而且,好吧......我希望能够保持几年后我回过头来使用我自己的代码,哈哈,所以这不是一个好的选择。

如何获得类似的正则表达式以在 C++ 中工作?

注意:这一切都必须在单个“std::regex”对象中完成,因为我正在编写一个库,用户可以在其中传递字符串以定义自己的正则表达式,我希望这些用户能够在需要时在他们的正则表达式中“定义”类似的子表达式。

字符串连接如何?

#define B64 "[A-Za-z0-9+/]"
#define B16 "[AEIMQUYcgkosw048]"
#define B04 "[AQgw]"

std::regex base64_regex(
        "^("
            "(" B64 "{4})*"
            "("
                B64 "{4}|"
                B64 "{2}" B16 "=|"
                B64 B04 "={2}"
            ")"
        ")?$");

我从评论中采纳了一个建议并检查了“boost”正则表达式,因为它支持“Perl”正则表达式。我试了一下,效果很好!

#include <boost/regex.hpp>

boost::regex base64_regex(
    "(?(DEFINE)"
        "(?<B64>[A-Za-z0-9+/])"
        "(?<B16>[AEIMQUYcgkosw048])"
        "(?<B04>[AQgw])"
    ")"
    "("
        "((?&B64){4})*"
        "("
            "(?&B64){4}|"
            "(?&B64){2}(?&B16)=|"
            "(?&B64)(?&B04)={2}"
        ")"
    ")?", boost::regex::perl);