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 (POSIX regex). Match a pattern against text, report
// every match with capture groups and index. Runnable: cc c.c && ./a.out
#include <regex.h>
#include <stdio.h>
#include <string.h>

#define MAX_GROUPS 10
#define MAX_MATCHES 2000

/* Run `pattern` (POSIX ERE) over `text` and print the tool's report:
   `N. "match" @ index -> [g1, g2]`. Returns the regcomp error, or 0 on ok. */
int run_regex(const char *pattern, const char *text, int ignore_case)
{
    regex_t re;
    int cflags = REG_EXTENDED;
    if (ignore_case) cflags |= REG_ICASE;

    int rc = regcomp(&re, pattern, cflags);
    if (rc != 0) {
        char err[128];
        regerror(rc, &re, err, sizeof err);
        fprintf(stderr, "error: %s\n", err);
        regfree(&re);
        return rc;
    }

    size_t nsub = re.re_nsub < MAX_GROUPS - 1 ? re.re_nsub + 1 : MAX_GROUPS;
    const char *p = text;
    int count = 0;
    while (count < MAX_MATCHES) {
        regmatch_t m[MAX_GROUPS];
        if (regexec(&re, p, nsub, m, 0) != 0) break;
        int idx = (int)(p - text) + m[0].rm_so;
        printf("%d. \"%.*s\" @ %d", ++count,
               (int)(m[0].rm_eo - m[0].rm_so), p + m[0].rm_so, idx);
        if (nsub > 1) {
            printf(" -> [");
            for (size_t g = 1; g < nsub; g++) {
                if (m[g].rm_so != -1)
                    printf("%s\"%.*s\"", g > 1 ? ", " : "",
                           (int)(m[g].rm_eo - m[g].rm_so), p + m[g].rm_so);
                else
                    printf("%s", g > 1 ? ", " : "");
            }
            printf("]");
        }
        putchar('\n');
        p += m[0].rm_eo; /* resume after the match */
        if (m[0].rm_eo == m[0].rm_so) p++; /* zero-width: advance one char */
    }
    if (count == 0) printf("(none)\n");
    regfree(&re);
    return 0;
}

int main(void)
{
    /* POSIX ERE has no \w — [[:alnum:]_] is the portable spelling. */
    const char *pattern = "[[:alnum:]_]+@[[:alnum:]_]+\\.[[:alnum:]_]+";
    const char *text = "mail@x.com nope bob@test.org";
    return run_regex(pattern, text, 1 /* ignore case */);
}

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 →