代码之家  ›  专栏  ›  技术社区  ›  Lightness Races in Orbit

对于正则表达式替换字符串中的Perl \l是否存在C++等价物?

  •  0
  • Lightness Races in Orbit  · 技术社区  · 6 年前

    I can replace characters with their lowercase version 像这样:

    my $str = "HELLO WORLD HOW ARE YOU TODAY";
    $str =~ s/([AEIOU])/\L\1/g;
    print $str;  # HeLLo WoRLD HoW aRe You ToDaY";
    

    如何用C++做这个 std::regex_replace ? 我可以把它转换成某种模式来激活像这样的神奇功能吗?

    (真正的搜索模式更复杂,否则我就不用正则表达式手工完成了!)

    1 回复  |  直到 6 年前
        1
  •  0
  •   Lightness Races in Orbit    6 年前

    不,没有。

    最后,我将SO中的不同代码位改编为以下内容:

    #include <regex>
    #include <string>
    #include <iostream>
    
    // Regex replacement with callback.
    // f should be compatible with std::string(const std::smatch&).
    // Adapted from code by John Martin (CC-by-SA 3.0).
    //   (https://stackoverflow.com/a/37516316/560648)
    template <typename UnaryFunction>
    inline std::string RegexReplace(const std::string& source, const char* const re_str, UnaryFunction f, size_t* numMatches = nullptr)
    {
        try
        {
            std::string s;
    
            std::smatch::difference_type positionOfLastMatch = 0;
            std::string::const_iterator first = std::begin(source), last = std::end(source);
            auto endOfLastMatch = first;
    
            if (numMatches)
                *numMatches = 0;
    
            auto callback = [&](const std::smatch& match)
            {
                auto positionOfThisMatch = match.position(0);
                auto diff = positionOfThisMatch - positionOfLastMatch;
    
                auto startOfThisMatch = endOfLastMatch;
                std::advance(startOfThisMatch, diff);
    
                s.append(endOfLastMatch, startOfThisMatch);
                s.append(f(match));
    
                auto lengthOfMatch = match.length(0);
    
                positionOfLastMatch = positionOfThisMatch + lengthOfMatch;
    
                endOfLastMatch = startOfThisMatch;
                std::advance(endOfLastMatch, lengthOfMatch);
    
                if (numMatches)
                    (*numMatches)++;
            };
    
            std::regex re{re_str};
            std::sregex_iterator begin(first, last, re), end;
            std::for_each(begin, end, callback);
    
            s.append(endOfLastMatch, last);
            return s;
        }
        catch (const std::regex_error&)
        {
            return "";
        }
    }
    
    int main()
    {
        // Change all letters but the first to lower case, but only in
        // words starting with a vowel
    
        const std::string str = "HELLO WORLD HOW ARE YOU TODAY";
        auto lowercaseSecondSubmatch = [](const std::smatch& match) -> std::string
        {
            if (match.size() != 3)
                return "WTF";
    
            std::string result = match.str(0);
    
            // Lowercase the second submatch
            const auto pos = match.position(2) - match.position(0);
            const auto len = match.length(2);
            const auto start = result.begin() + pos;
            const auto end   = result.begin() + pos + len;
            std::transform(start, end, start, ::tolower);
    
            return result;
        };
    
        size_t n = 0;
        std::cout << RegexReplace(str, R"REGEX(\b([AEIOUY])([A-Z]+))REGEX", lowercaseSecondSubmatch, &n) << '\n';
        std::cout << n << " matches\n";
    }
    

    live demo )