regex(3)
๐ regex(3) โ the POSIX regex girlies ๐
okay so bestie, welcome to regex(3), aka the library functions manual for regcomp, regexec, regerror and regfree โ your four besties for matching patterns in strings. no cap, this is the whole squad.
โจ NAME โจ
regcomp, regexec, regerror, regfree โ POSIX regex functions. that's the lineup, that's the group chat. ๐
๐ LIBRARY ๐
Standard C library (libc, -lc). she lives in libc, she's literally always there for you. ๐ซถ
๐ SYNOPSIS ๐
#include <regex.h>
int regcomp(regex_t *restrict preg, const char *restrict regex,
int cflags);
int regexec(const regex_t *restrict preg,
const char *restrict string,
size_t n, regmatch_t pmatch[_Nullable restrict n],
int eflags);
size_t regerror(size_t errbuf_size;
int errcode, const regex_t *_Nullable restrict preg,
char errbuf[_Nullable restrict errbuf_size],
size_t errbuf_size);
void regfree(regex_t *preg);
typedef struct {
size_t re_nsub;
} regex_t;
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
typedef /* ... */ regoff_t;
(yes the regerror sig up there is a little cursed, we're keeping it exactly as-is, it's giving โจsource fidelityโจ)
๐ธ DESCRIPTION ๐ธ
๐ง Compilation ๐ง
regcomp() takes a regular expression and compiles it into a form that's suitable for the subsequent regexec() searches. it's the glow-up phase, basically. ๐
On success, the pattern buffer at *preg is initialized. regex is a null-terminated string. and listen โ the locale must be the same when running regexec(). same locale, same vibe, periodt.
After regcomp() succeeds, preg->re_nsub holds the number of subexpressions in regex. so if you pass preg->re_nsub + 1 as n to regexec(), that's sufficient to capture all matches. iconic math honestly.
cflags is the bitwise OR of zero or more of the following:
REG_EXTENDEDโ use POSIX Extended Regular Expression syntax when interpretingregex. if it's not set, POSIX Basic Regular Expression syntax is used instead. two different energies, pick your fighter.REG_ICASEโ do not differentiate case. subsequentregexec()searches using this pattern buffer will be case insensitive. she does NOT care about your capital letters, lowercase era fr fr.REG_NOSUBโ report only overall success.regexec()will use onlypmatchforREG_STARTEND, ignoringn. she's just here for the yes/no, she's not doing detail work.REG_NEWLINEโ okay this one has layers, let's unpack:- Match-any-character operators don't match a newline. ๐ซ
- A nonmatching list (
[^...]) not containing a newline does not match a newline. - Match-beginning-of-line operator (
^) matches the empty string immediately after a newline, regardless of whethereflags, the execution flags ofregexec(), containsREG_NOTBOL. - Match-end-of-line operator (
$) matches the empty string immediately before a newline, regardless of whethereflagscontainsREG_NOTEOL.
๐ Matching ๐
regexec() is used to match a null-terminated string against the compiled pattern buffer in *preg, which must have been initialized with regcomp(). (no shortcutting bestie, you gotta compile first.)
eflags is the bitwise OR of zero or more of the following flags:
REG_NOTBOLโ the match-beginning-of-line operator always fails to match (but see the compilation flagREG_NEWLINEabove ๐). this flag may be used when different portions of a string are passed toregexec()and the beginning of the string should not be interpreted as the beginning of the line. tl;dr: it's a chunk, not a fresh start.REG_NOTEOLโ the match-end-of-line operator always fails to match (but see the compilation flagREG_NEWLINEabove ๐).REG_STARTENDโ match[string + pmatch[0].rm_so, string + pmatch[0].rm_eo)instead of[string, strnul(string)). this allows matching embedded NUL bytes, which is lowkey powerful. if any matches are returned (REG_NOSUBwasn't passed toregcomp(), the match succeeded, andn > 0), they overwritepmatchas usual, and the match offsets remain relative tostring(notstring + pmatch[0].rm_so). this flag is a BSD extension, not present in POSIX. she's a guest star, not main cast.
๐ Match offsets ๐
Unless REG_NOSUB was passed to regcomp(), it is possible to obtain the locations of matches within string: regexec() fills n elements of pmatch with results: pmatch[0] corresponds to the entire match, pmatch[1] to the first subexpression, etc. if there were more matches than n, they are discarded; if fewer, the unused elements of pmatch are filled with -1s. (ghosted with a -1, brutal but honest ๐)
Each returned valid (non--1) match corresponds to the range [string + rm_so, string + rm_eo).
regoff_t is a signed integer type capable of storing the largest value that can be stored in either an ptrdiff_t type or a ssize_t type. big container energy.
๐ญ Error reporting ๐ญ
regerror() is used to turn the error codes that can be returned by both regcomp() and regexec() into error message strings. she's the translator, she turns numbers into actual sentences you can read.
If preg isn't a null pointer, errcode must be the latest error returned from an operation on preg. don't be bringing me stale error codes, i will know.
If errbuf_size isn't 0, up to errbuf_size bytes are copied to errbuf; the error string is always null-terminated, and truncated to fit. always null-terminated bestie, it's the law.
๐ฆ Freeing ๐ฆ
regfree() deinitializes the pattern buffer at *preg, freeing any associated memory. and *preg must have been initialized via regcomp(). you can't free what you never compiled, that's not a thing.
๐ RETURN VALUE ๐
regcomp()returns zero for a successful compilation or an error code for failure. zero = slay, anything else = we have a problem.regexec()returns zero for a successful match orREG_NOMATCHfor failure.regerror()returns the size of the buffer required to hold the string. she tells you how much room she needs, so polite.
๐ ERRORS ๐
The following errors can be returned by regcomp():
REG_BADBRโ invalid use of back reference operator.REG_BADPATโ invalid use of pattern operators such as group or list.REG_BADRPTโ invalid use of repetition operators such as using'*'as the first character. girl you can't start with a*, that's not how this works ๐ญREG_EBRACEโ un-matched brace interval operators.REG_EBRACKโ un-matched bracket list operators.REG_ECOLLATEโ invalid collating element.REG_ECTYPEโ unknown character class name.REG_EENDโ nonspecific error. this is not defined by POSIX. she's mysterious, she's undefined, she's giving enigma.REG_EESCAPEโ trailing backslash.REG_EPARENโ un-matched parenthesis group operators.REG_ERANGEโ invalid use of the range operator; for example, the ending point of the range occurs prior to the starting point. backwards range, backwards behaviour.REG_ESIZEโ compiled regular expression requires a pattern buffer larger than 64 kB. this is not defined by POSIX.REG_ESPACEโ the regex routines ran out of memory. ๐REG_ESUBREGโ invalid back reference to a subexpression.
๐ ATTRIBUTES ๐
for an explanation of the terms used in this section, see attributes(7).
regcomp(),regexec()โ Thread safety:MT-Safe localeregerror()โ Thread safety:MT-Safe envregfree()โ Thread safety:MT-Safe
โญ STANDARDS โญ
POSIX.1-2008.
๐ฐ๏ธ HISTORY ๐ฐ๏ธ
POSIX.1-2001.
Prior to POSIX.1-2008, regoff_t was required to be capable of storing the largest value that can be stored in either an off_t type or a ssize_t type. they changed the requirements, character development arc honestly.
โ ๏ธ CAVEATS โ ๏ธ
re_nsub is only required to be initialized if REG_NOSUB wasn't specified, but all known implementations initialize it regardless. so like, technically optional, practically always there. iykyk.
Both regex_t and regmatch_t may (and do) have more members, in any order. always reference them by name. do NOT assume the layout bestie, that's how you get humbled. ๐
โจ EXAMPLES โจ
#include <stdcountof.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
static const char *const str =
"1) John Driverhacker;\n2) John Doe;\n3) John Foo;\n";
static const char *const re = "John.*o";
int main(void)
{
static const char *s = str;
regex_t regex;
regmatch_t pmatch[1];
regoff_t off, len;
if (regcomp(®ex, re, REG_NEWLINE))
exit(EXIT_FAILURE);
printf("String = \"%s\"\n", str);
printf("Matches:\n");
for (unsigned int i = 0; ; i++) {
if (regexec(®ex, s, countof(pmatch), pmatch, 0))
break;
off = pmatch[0].rm_so + (s - str);
len = pmatch[0].rm_eo - pmatch[0].rm_so;
printf("#%u:\n", i);
printf("offset = %jd; length = %jd\n", (intmax_t) off,
(intmax_t) len);
printf("substring = \"%.*s\"\n", len, s + pmatch[0].rm_so);
s += pmatch[0].rm_eo;
}
exit(EXIT_SUCCESS);
}
๐ซถ SEE ALSO ๐ซถ
The glibc manual section, Regular Expressions
and that's the whole page bestie!! ๐ this one came from the Linux man-pages 6.20, dated 2026-02-22, and it's regex(3) โ go forth and match some patterns, you've got this ๐โจ๐ฆ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 1995, Graeme W. Wilford <G.Wilford@ee.surrey.ac.uk>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms