基本std::regex,将查询转换为有效掩码

basic std::regex, translate query to valid mask

本文关键字:转换 有效 查询 掩码 std regex 基本      更新时间:2023-10-16

我需要用两个特殊的simbols实现简单的regex搜索-星号(*)作为任意数量的字符,问号(?)作为任意单个字符。查询中的任何其他符号都必须按原样解释。

主要问题是如何将输入掩码转换为有效的std::regex掩码。我把*翻译成.*和?像(点)。所有其他字符都必须转义或按原样解释。问题是,如果我转义任何字符,std::regex都会引发异常,但以下字符除外:$^[\|.

它引发了一个例外,如果我逃离符号。如果不转义]符号,则会引发一个异常。所以我根本无法搜索]sign。

我想,这是我的失败,我做错了什么。但我不明白我的失败在哪里。

我使用的是VS 2017和C++17选项。

#include <string>
#include <regex>
void translate_mask (std::wstring & mask)
{
std::wstring basic (L"^");
for (auto c : mask)
{
switch (c)
{
case L'*':
basic += L".*";
break;
case L'?':
basic += L'.';
break;
case L'$':
case L'^':
case L'[':
case L'':
case L'|':
case L'.':
basic += L'' + std::wstring (1, c);
break;
case L']':      
basic += L'.';      // workaround? ']' char cannot be escaped, so interpret it is as any single char
// uncomment any of these lines and exception will be raisen from std::wregex ctor
//basic += L'' + std::wstring (1, c);
//basic += c;
break;

default:
basic += c;
}
}
basic += L'$';
mask = std::move (basic);
}
void load_string (std::wstring & str)
{
// load string from some database, for example
str = L"[ hello | world of stack ]";
}
bool find (const std::wstring & str, const std::wstring & mask)
{
try
{
std::wregex r (mask, std::wregex::basic);
std::wsmatch m;
return std::regex_search (str, m, r);
}
catch (...)
{
return false;
}
}
int main ()
{
std::wstring mask, str;
// std::wcin >> mask;
// example input:
mask = L"[ hello | world of * ]";
load_string (str);
translate_mask (mask);
bool res = find (str, mask);   // returns true
return 0;
}

如果我试图将"]"字符转义为"\]",find函数将引发异常。如果我根本不转义"]",find函数将引发一个异常。请参阅translate_mask功能中的case L']':

您使用的是basic语法(原因不清楚,因为您似乎是根据ECMASCript语法进行思考的)。在该语法中,管道|并不特殊,不应转义。]有点特殊,但只是作为一个括号表达式的一部分(当你逃离[时,你不会有它);除此之外,它不应该逃脱。

有了这些更改,您的示例就起作用了。

注意还有其他特殊字符,例如括号()和大括号{}