c++ - 如何在 c++11 中使用正则表达式找到确切的子字符串?
问题描述
我正在尝试查找未被其他a-zA-Z0-9
符号包围的子字符串。
例如:我想找到 substring hello
,所以它不会匹配hello1
orhellow
但会匹配Hello
and heLLo!@#$%
。我在下面有这样的样本。
std::string s = "1mySymbol1, /_mySymbol_ mysymbol";
const std::string sub = "mysymbol";
std::regex rgx("[^a-zA-Z0-9]*" + sub + "[^a-zA-Z0-9]*", std::regex::icase);
std::smatch match;
while (std::regex_search(s, match, rgx)) {
std::cout << match.size() << "match: " << match[0] << '\n';
s = match.suffix();
}
结果是:
1match: mySymbol
1match: , /_mySymbol_
1match: mysymbol
但我不明白为什么第一次出现1mySymbol1
也符合我的正则表达式?
如何创建一个适当的正则表达式来忽略这些字符串?
UDP
如果我喜欢这样
std::string s = "mySymbol, /_mySymbol_ mysymbol";
const std::string sub = "mysymbol";
std::regex rgx("[^a-zA-Z0-9]+" + sub + "[^a-zA-Z0-9]+", std::regex::icase);
然后我在中间只找到子字符串
1match: , /_mySymbol_
并且不要在开头和结尾找到子字符串。
解决方案
正则表达式[^a-zA-Z0-9]*
将匹配 0 个或更多字符,因此[^a-zA-Z0-9]*mysymbol[^a-zA-Z0-9]*
匹配mysymbol
in完全有效1mySymbol1
(允许不区分大小写)。如您所见,当您改用[^a-zA-Z0-9]+
(匹配 1 个或多个字符)时,此问题已得到解决。
通过您的更新,您会发现这与开头或结尾的字符串不匹配。那是因为[^a-zA-Z0-9]+
必须匹配 1 个或多个字符(在字符串的开头或结尾不存在)。
你有几个选择:
- 使用开始/结束锚点:(
(?:[^a-zA-Z0-9]+|^)mysymbol(?:[^a-zA-Z0-9]+|$)
非字母数字或字符串开头,后跟mysymbol
,后跟非字母数字或字符串结尾)。 - 使用负前瞻和负后瞻:(
(?<![a-zA-Z0-9])mysymbol(?![a-zA-Z0-9])
匹配mysymbol
之前或之后没有字母数字字符)。请注意,使用此匹配将不包括 before/after 的字符mysymbol
。
我建议使用https://regex101.com/来玩转正则表达式。它列出了您可以使用的所有不同结构。
推荐阅读
- scala - 为什么 Scala 加载命令在 Windows 10 命令提示符下的 REPL 中不起作用?
- c# - 在我的 DbContext 上使用 .Include() 方法时出现网络错误
- unity3d - unity fps 跳跃与角色控制器
- laravel - laravel 5.2 在所有控制器中传递变量
- javascript - 使用相同的 HTML 模板/文件时重定向到不同的页面?
- swift - UICollectionView 在屏幕旋转时调整大小
- flutter - 如何使用 Flutter 获取 SIM、配置、位置、网络信息
- ruby-on-rails - Rails 6 devise_ldap_authenticable 保存具有不同用户名大小写的重复用户
- javascript - 用于项目活动状态的 Bootstrap 4 自定义导航栏
- ios - send_keys() 方法不适用于在 iPhone 模拟器上输入密码