首页 > 解决方案 > C++ 正则表达式错误!方括号表达式不适用于 icase 标志

问题描述

// regex_replace example
#include <iostream>
#include <string>
#include <regex>
#include <iterator>

int main ()
{
  std::string INPUT = "Replace_All_Characters_With_Anything";
  std::string OUTEXP = "0";
  std::regex expression("[A-Za-z]", std::regex_constants::icase);
  std::cout << std::regex_replace(INPUT, expression, OUTEXP);

  return 0;
}

这在这里有效:http ://cpp.sh/6gb5a 这在这里有效:https ://regexr.com/5bt9d

问题似乎归结为是否使用 icase 标志。A in All、C in Characters、W in With 等不会因为存在下划线而被替换。该错误似乎是,[]仅当所述字符在不匹配之后没有出现时,才使用匹配事物。

似乎确实有一个快速解决方法,如果括号后面跟着一个 {1},那么它就可以工作。

例子:[A-Za-z]{1}

编译器:Microsoft Visual Studio Community 2019 / 版本 16.7.3 / c++17

也在 c++14 中测试过,同样的不良行为

预期结果:
在此处输入图像描述

我的结果:
在此处输入图像描述

标签: c++regexvisual-c++

解决方案


不确定这是否是回答的适当用途。但这是一个已知的错误,看起来这个错误已经知道几个月了。据我所知,没有 ETA 修复。

https://github.com/microsoft/STL/issues/993

看起来 RE2 是推荐的替代正则表达式库。

https://github.com/google/re2/

我将创建一个函数,而不是使用另一个库,该函数可用于拦截和更改正则表达式字符串作为临时修复。无论是否使用 icase 标志都应该有效。

测试代码:https ://rextester.com/LSNW3495

// add '{1}' after square bracket ranges unless there already is a quantifier or alternation such as '?' '*' '+' '{}' 
std::string temporaryBugFix(std::string exp)
{
    enum State
    {
        start,
        skipNext,
        lookForEndBracket,
        foundEndBracket,
    };

    State state = start;
    State prevState = start;

    int p = -1;
    std::vector<int> positionsToFix;

    for (auto c : exp)
    {
        ++p;

        switch (state)
        {
        case start:
            if (c == '\\')
            {
                prevState = state;
                state = skipNext;
            }
            else if (c == '[')
                state = lookForEndBracket;

            continue;

        case skipNext:
            state = prevState;
            continue;

        case lookForEndBracket:
            if (c == '\\')
            {
                prevState = state;
                state = skipNext;
            }
            else if (c == ']')
            {
                state = foundEndBracket;
                if (p + 1 == exp.length())
                    positionsToFix.push_back(p + 1);
            }
            continue;

        case foundEndBracket:
            if (c != '+' && c != '*' && c != '?')
                positionsToFix.push_back(p);
            state = start;
            continue;
        }
    }

    // check for valid curly brackets so we don't add an additional one
    std::string s = exp;
    std::smatch m;
    std::regex e("\\{\\d+,?\\d*?\\}");

    int offset = 0;
    vector<int> validCurlyBracketPositions;
    while (regex_search(s, m, e))
    {
        validCurlyBracketPositions.push_back(m.position(0) + offset);
        offset += m.position(0) + m[0].length();
        s = m.suffix();
    }

    // remove valid curly bracket positions from the fix vector
    for (auto p : validCurlyBracketPositions)
        positionsToFix.erase(std::remove(positionsToFix.begin(), positionsToFix.end(), p), positionsToFix.end());

    // insert the fixes
    for (int i = positionsToFix.size(); i--; )
        exp.insert(positionsToFix[i], "{1}");

    return exp;
}

推荐阅读