如何在GoogleTest正则匹配器中实现大小写不敏感正则匹配?
问题
我想了解如何在GoogleTest的正则匹配器(如ContainsRegex)中实现大小写不敏感的正则匹配。
我尝试过在表达式前添加(?i)或用/+/i包裹表达式,但均未成功:
EXPECT_THAT("ExpreSSion", ContainsRegex("(?i)expression")); EXPECT_THAT("ExpreSSion", ContainsRegex("/expression/i"));
有人知道GoogleTest使用的是什么正则表达式引擎,以及它是否支持大小写不敏感表达式吗?
不太理想的临时解决方案
我目前的解决办法是在匹配前将所有字符转为小写,但这会降低单元测试的可读性,而且我认为这并非良好实践。我希望测试实际生成的数据,而非在测试前修改它。
EXPECT_THAT(toLower("ExpreSSion"), ContainsRegex("expression"));
当然,在表达式编译期已知的示例中,可以为每个字符显式匹配任意大小写,但这样可读性极差
EXPECT_THAT("ExpreSSion", ContainsRegex("[Ee][Xx][Pp][Rr][Ee][Ss][Ss][Ii][Oo][Nn]"));
这可以自动化实现,但我们真的需要做到这种程度才能忽略大小写匹配字符串吗?该库肯定原生支持这个特性吧?
auto ContainsRegexCaseInsensitive(const std::string &expr) { static const auto ignoreLetterCases = [](const std::string &expr) -> std::string { // Replacinging letters with [<upper><lower>] // ... }; return ContainsRegex(ignoreLetterCases("expression")); } EXPECT_THAT("ExpreSSion", ContainsRegexCaseInsensitive("expression"));
解决方案
GoogleTest默认使用RE2正则表达式引擎(Google自研的高效正则库),它原生支持大小写不敏感匹配,你之前的问题是用错了语法:
- 正确的内联标志用法
RE2支持(?i)作为大小写不敏感的内联标志,将其放在正则表达式开头即可对整个表达式生效:
EXPECT_THAT("ExpreSSion", ContainsRegex("(?i)expression"));
如果只需让表达式的某一部分忽略大小写,可以用(?i:...)包裹目标片段,精准控制作用范围:
EXPECT_THAT("ExpreSSion123", ContainsRegex("(?i:expression)123"));
为什么
/expression/i不生效
这种/模式/i的写法是Perl风格的正则语法,RE2并不支持,它会把/和i当作普通匹配字符处理,自然无法实现大小写不敏感。旧版本兼容方案
如果你的GoogleTest版本较旧(未集成RE2),可以自己封装一个简洁的大小写不敏感匹配器:
#include "gmock/gmock.h" #include "re2/re2.h" MATCHER_P(ContainsRegexCaseInsensitive, pattern, "") { return RE2::PartialMatch(arg, RE2(pattern, RE2::CaseInsensitive)); } // 使用示例 EXPECT_THAT("ExpreSSion", ContainsRegexCaseInsensitive("expression"));
这种原生方案无需修改测试数据,也不用生成冗长的字符组,既能保证测试可读性,又符合最佳实践。
内容的提问来源于stack exchange,提问作者Smartskaft2
相关产品推荐
相关产品推荐

