C++11/正则表达式 - 查找精确字符串,转义

13

假设用户提供了一个字符串,它可以包含任何类型的字符。例如:

std::string s1{"hello world");
std::string s1{".*");
std::string s1{"*{}97(}{.}}\\testing___just a --%#$%# literal%$#%^"};
...

现在我想在一些文本中搜索出现 >> 紧接着输入字符串 s1 后面再紧跟着 << 的情况。为此,我有以下代码:

现在我希望搜索文本中是否存在>>后面紧跟着输入字符串s1,然后再紧跟着<<的部分内容。为此,我编写了以下代码:

std::string input; // the input text
std::regex regex{">> " + s1 + " <<"};

if (std::regex_match(input, regex)) {
     // add logic here
}

如果s1中不含任何特殊字符,这段代码运行得很好。然而,如果s1包含了一些被正则表达式引擎识别的特殊字符,它就无法工作。

我该如何转义s1,以使std::regex将其视为字面值,从而不解释s1?换句话说,正则表达式应该是:

std::regex regex{">> " + ESCAPE(s1) + " <<"};

在标准库中是否有类似于ESCAPE()的函数?

重要提示:我简化了我的问题。在实际情况中,正则表达式要复杂得多。由于我只遇到了s1被解释的问题,所以我省略了这些细节。


2
使用正则表达式的特定原因是什么?这可以使用string.find完成。 - Austin Brunkhorst
@Austin Brunkhorst 是的,我需要正则表达式。我简化了问题,因为我只是在纠结于字符串被引擎解释的事实。在我的实际情况中,正则表达式更加复杂。 - Karel Demeester
@ForceBru 有两个输入:s1 和一些文本。字符串s1用于动态构建正则表达式,该表达式用于在输入文本中进行搜索。 - Karel Demeester
我会尝试构建一个正则表达式来提取可测试的部分,然后直接比较字符串:std::regex regex{">> (.*?) <<"}; ... if(match.str(1) == s1)... 这种方法在你的情况下可行吗? - Galik
1
这与“如何转义字符串以在Boost Regex中使用”有关,因为std :: regex在很大程度上基于boost :: regex。您可以参考该问题以获取答案。 - Cornstalks
显示剩余3条评论
1个回答

11

您需要使用\转义字符串中的所有特殊字符。最简单直接的方法是在创建表达式regex之前使用另一个表达式来清理输入字符串。

// matches any characters that need to be escaped in RegEx
std::regex specialChars { R"([-[\]{}()*+?.,\^$|#\s])" };

std::string input = ">> "+ s1 +" <<"; 
std::string sanitized = std::regex_replace( input, specialChars, R"(\$&)" );

// "sanitized" can now safely be used in another expression

2
包括 ^ 是有意义的,但你用反斜杠转义了它。我很好奇为什么在这种情况下你要用反斜杠转义它。此外,你还包括了 \s,它匹配空格,但我不确定你为什么需要它(也许是换行符处理?我不知道;我记不清 std::regex 如何处理换行符以及是否转义它们会有所不同)。在我的上一条评论中,我试图说“\”也应该包含在 specialChars 中,但 Markdown 吞掉了它。 - Cornstalks
2
关于 #,它需要转义吗? - Karel Demeester
2
而逗号,呢?为什么需要转义? - Karel Demeester
4
只需要使用这些字符 [\^$.|?*+(){} 就可以通过 \ 转义。根据正则表达式的说明。 - c00000fd
1
@c00000fd 这个列表不足以处理例如 [({])} 的输入。 - Mikhail
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接