在 C++ 中使用“DEFINED”子表达式组合复杂的正则表达式
Posted
技术标签:
【中文标题】在 C++ 中使用“DEFINED”子表达式组合复杂的正则表达式【英文标题】:Composing complex regular expressions with "DEFINED" subexpressions in C++ 【发布时间】:2021-03-04 02:27:17 【问题描述】:我正在尝试用 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”对象中完成,因为我正在编写一个库,用户可以在其中传递一个字符串来定义他们自己的正则表达式,我想要如果需要,这些用户能够在他们的正则表达式中“定义”类似的子表达式。
【问题讨论】:
看看this post 你也可以试试 (?P字符串连接怎么样?
#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"
")"
")?$");
【讨论】:
看起来确实很干净,但不幸的是它不适用于我的用例。最终,我正在编写一个库,它允许用户从 XML 文件中提供他们自己的正则表达式字符串,并且我希望用户能够自己“定义”子表达式。因此,这一切都必须在一个字符串中完成。【参考方案2】:我接受了 cmets 的建议并检查了“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);
【讨论】:
以上是关于在 C++ 中使用“DEFINED”子表达式组合复杂的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们需要在 C++ 头文件中使用“#if defined Identifier”?
在 C++ 中使用 std::complex<T> 创建复无穷大