Skip to content

Regex Tester — C++ source

Test regular expressions against any text with all flags (g/i/m/s/u/y). See every match, its index and capture groups, plus the constructed pattern. 100% in-browser.

This is the C++ implementation — the same logic the interactive tool runs, in a shareable, citable form.

// regex-tester — C++ port. Match a pattern against text, report every match
// with capture groups and index (std::regex, ECMAScript grammar).
#include <iostream>
#include <regex>
#include <string>
#include <vector>

struct RegexMatch {
    std::string match;
    std::size_t index;
    std::vector<std::string> groups; // "" where a group did not participate
};

// JS flag letters map onto syntax_option_type; s (dotall) is the ECMAScript
// default for std::regex, u is always on for char, y has no equivalent.
std::regex::flag_type compile_flags(const std::string &flags) {
    auto f = std::regex::ECMAScript;
    for (char c : flags) {
        if (c == 'i') f |= std::regex::icase;
        else if (c == 'm') f |= std::regex::multiline; // C++17
    }
    return f;
}

std::vector<RegexMatch> run_regex(const std::string &pattern,
                                  const std::string &flags,
                                  const std::string &text) {
    std::vector<RegexMatch> out;
    try {
        std::regex re(pattern, compile_flags(flags));
        std::size_t limit = flags.find('g') != std::string::npos ? 2000 : 1;
        auto last = std::sregex_iterator();
        for (auto it = std::sregex_iterator(text.begin(), text.end(), re);
             it != last && out.size() < limit; ++it) {
            std::smatch m = *it;
            std::vector<std::string> groups;
            for (std::size_t g = 1; g < m.size(); ++g)
                groups.push_back(m[g].matched ? m[g].str() : "");
            out.push_back({m.str(), (std::size_t)m.position(), groups});
        }
    } catch (const std::regex_error &e) {
        std::cerr << "error: " << e.what() << '\n';
    }
    return out;
}

// Render a result the way the tool's UI does:
// `N. "match" @ index -> [g1, g2]`, or `(none)` when empty.
void format_matches(const std::vector<RegexMatch> &ms) {
    if (ms.empty()) { std::cout << "(none)\n"; return; }
    for (std::size_t i = 0; i < ms.size(); ++i) {
        const auto &m = ms[i];
        std::cout << i + 1 << ". \"" << m.match << "\" @ " << m.index;
        if (!m.groups.empty()) {
            std::cout << " -> [";
            for (std::size_t g = 0; g < m.groups.size(); ++g)
                std::cout << (g ? ", " : "") << m.groups[g];
            std::cout << "]";
        }
        std::cout << '\n';
    }
}

int main() {
    auto ms = run_regex(R"((\w+)@(\w+)\.(\w+))", "g", "mail@x.com nope bob@test.org");
    format_matches(ms);
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →