#include #include #include regex_t regex; #define MAX_MATCH 5 // This is the number of capture groups + 1 #define RESET "\x1b[0m" int regmatch(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { // returns number of matches found. (Max nmatch) int matches = 0; int offset = 0; int ret; while (matches < nmatch) { ret = regexec(preg, string + offset, nmatch - matches, pmatch + matches, eflags); if (!ret) { int current = offset; offset += pmatch[matches].rm_eo; pmatch[matches].rm_so += current; pmatch[matches].rm_eo += current; matches++; } else if (ret == REG_NOMATCH) { break; } else { break; } } return matches; } const char *clean_string(const char *badansi) { static char buffer[1024]; char *cp; strcpy(buffer, badansi); cp = buffer; while ((cp = strstr(cp, "\x1b")) != NULL) { *cp = '~'; }; return buffer; } void test(const char *trythis) { regmatch_t regmatches[MAX_MATCH]; int matches, x; const char *clean = clean_string(trythis); printf("TEST (%s)\n", clean); matches = regmatch(®ex, trythis, MAX_MATCH, regmatches, 0); if (matches == 0) { printf("No matches.\n"); } else { printf("%d matches:\n", matches); for (x = 0; x < matches; x++) { printf("%d (%d - %d)\n", x, regmatches[x].rm_so, regmatches[x].rm_eo); printf(" %*s [%.*s]\n", regmatches[x].rm_so, "", regmatches[x].rm_eo - regmatches[x].rm_so, clean + regmatches[x].rm_so); } } } void test_(const char *trythis) { int ret; char msgbuf[100]; const char *p = trythis; // safe printing (maybe) strcpy(msgbuf, trythis); char *fixup = msgbuf; while ((fixup = strstr(fixup, "\x1b")) != NULL) { *fixup = '^'; }; printf("Test: [%s]%s\n", msgbuf, RESET); regmatch_t matches[MAX_MATCH]; while (1) { ret = regexec(®ex, p, MAX_MATCH, matches, 0); if (!ret) { printf("MATCH!\n"); for (int i = 0; i < MAX_MATCH; i++) { int start, finish; if (matches[i].rm_so == -1) break; start = matches[i].rm_so; finish = matches[i].rm_eo; // %.*s = length to print, char * to use strncpy(msgbuf, p + start, (finish - start)); msgbuf[finish - start] = 0; fixup = msgbuf; while ((fixup = strstr(fixup, "\x1b")) != NULL) { *fixup = '^'; }; // printf("'%.*s'%s %d : %d - %d\n", (finish - start), p + start, RESET, // i, start, finish); printf("'%s' %d : %d - %d\n", msgbuf, i, start, finish); }; p += matches[0].rm_eo; } else if (ret == REG_NOMATCH) { printf("Sorry, no matches.\n"); break; } else { regerror(ret, ®ex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "Regex match failed: %s\n", msgbuf); } } return; } int main(int argc, char *argv[]) { // char RX[] = "(\x1b\[(?:\\d+|;)+[a-zA-Z])"; // char RX[] = "([a-z][a-z]([0-9]+))"; char RX[] = "([a-z][a-z]([0-9]+))"; char msgbuf[100]; int ret; if ((ret = regcomp(®ex, RX, REG_EXTENDED | REG_NEWLINE))) { regerror(ret, ®ex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "Regex compile failed: %s\n", msgbuf); return 1; } test("this will fail."); test("this has ab5 ab55 zd3 three matches."); regfree(®ex); // if ( regcomp( ®ex, "(\x1b\[(?:[0-9]|;)+[a-zA-Z])", // REG_EXTENDED|REG_NEWLINE ) ) { if ( regcomp( ®ex, // "(\x1b\[([0-9]+|;)+[a-zA-Z])", REG_EXTENDED|REG_NEWLINE ) ) { if ( regcomp( // ®ex, "\x1b\[[0-9]+(;[0-9]+)+?[a-zA-Z]", REG_EXTENDED|REG_NEWLINE ) ) { if (regcomp(®ex, "\x1b\[[0-9]+(;[0-9]+)*?[a-zA-Z]", REG_EXTENDED | REG_NEWLINE)) { regerror(ret, ®ex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "Regex compile failed: %s\n", msgbuf); return 1; }; test("\x1b[1;1H\x1b[2J\x0cMystic BBS\x1b[6n"); test("\x1b[5;1HMEEP."); test("\x1b[0;1;34;47mHello"); regfree(®ex); // \s matches space, FORM FEED. Ouch! NO! if (regcomp(®ex, "[a-zA-Z]+( [a-zA-Z]+)+", REG_EXTENDED | REG_NEWLINE)) { regerror(ret, ®ex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "Regex compile failed: %s\n", msgbuf); return 1; }; test("\x1b[1;1H\x1b[2J\x0cMystic BBS\x1b[6n"); test("\x1b[5;1HMEEP is cool for cats."); regfree(®ex); return 0; }