首页 > 解决方案 > 如何在 c++11 中使用正则表达式找到确切的子字符串?

问题描述

我正在尝试查找未被其他a-zA-Z0-9符号包围的子字符串。

例如:我想找到 substring hello,所以它不会匹配hello1orhellow但会匹配Helloand 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_

并且不要在开头和结尾找到子字符串。

标签: c++regexc++11

解决方案


正则表达式[^a-zA-Z0-9]*将匹配 0 个或更多字符,因此[^a-zA-Z0-9]*mysymbol[^a-zA-Z0-9]*匹配mysymbolin完全有效1mySymbol1(允许不区分大小写)。如您所见,当您改用[^a-zA-Z0-9]+(匹配 1 个或多个字符)时,此问题已得到解决。

通过您的更新,您会发现这与开头或结尾的字符串不匹配。那是因为[^a-zA-Z0-9]+ 必须匹配 1 个或多个字符(在字符串的开头或结尾不存在)。

你有几个选择:

  1. 使用开始/结束锚点:((?:[^a-zA-Z0-9]+|^)mysymbol(?:[^a-zA-Z0-9]+|$)非字母数字或字符串开头,后跟mysymbol,后跟非字母数字或字符串结尾)。
  2. 使用负前瞻和负后瞻:((?<![a-zA-Z0-9])mysymbol(?![a-zA-Z0-9])匹配mysymbol之前或之后没有字母数字字符)。请注意,使用此匹配将不包括 before/after 的字符mysymbol

我建议使用https://regex101.com/来玩转正则表达式。它列出了您可以使用的所有不同结构。


推荐阅读