PCRE2 for C: embedding Perl-compatible regular expressions
PCRE2 is a library implementing regular expression pattern matching with a C API
At a glance
- What is it?
- PCRE2 gives C applications a portable regular expression engine with Unicode support, three code-unit widths, and an optional JIT. It suits software that needs direct control over compiled patterns, captures, character representations, and integration.
- Who is it for?
- Adopt PCRE2 when a C or C++ application needs Perl-compatible matching, Unicode support, selectable code-unit widths, or JIT compilation. Do not adopt it when simple fixed-string operations are sufficient or when managing an independent compiled library is an unreasonable cost.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why PCRE2 belongs in a C application's dependency graph
PCRE2 solves the problem of embedding regular expression matching in software that does not have a suitable expression engine through its language runtime. Its public interface consists of C functions, so an application can compile patterns, match subjects, retrieve capture offsets, and manage both compiled objects and match data through a direct API. The intended users are developers adding text processing to C or C++ programs, language runtimes, servers, command-line tools, and other software with its own build and deployment model.
The README describes a self-contained, portable library designed for embedding into existing projects and build systems. That portability has a practical meaning. An embedding project still has to select a supported build configuration, compile the code for its target, and package the resulting library. It does not eliminate native dependency management, but it does let the application remain in control of those choices.
PCRE2 supports Unicode and a wide range of Perl-compatible regular expression features. It can also accept input in different character encodings. This makes it relevant when matching text must handle more than byte-oriented ASCII input. The repository also contains package templates for 8-bit, 16-bit, and 32-bit variants, and the quickstart explicitly links the 8-bit library as lpcre2-8.
An optional JIT matching engine provides a second reason to consider PCRE2. Consumers can request it during the build, as shown by -DPCRE2_SUPPORT_JIT=ON. JIT is not required to compile patterns. It changes how matching code is generated, so an adopter still needs to decide whether that path belongs in the selected configuration and distribution.
PCRE2 is an engine rather than a complete text-processing application. Callers remain responsible for obtaining patterns and subjects, selecting options, interpreting captures, handling failures, and applying application-specific limits. Those responsibilities are particularly important when patterns come from users rather than fixed source code.
How PCRE2 compiles patterns and returns match offsets
The documented C example uses a direct object lifecycle. It calls pcre2_compile with PCRE2_ZERO_TERMINATED, which tells PCRE2 that the pattern is a zero-terminated string. The function also receives default options, an error number, an error offset, and a compile context. A successful result is a pcre2_code object. If compilation fails, the example reports an invalid pattern and exits without attempting a match.
After compilation, pcre2_match_data_create_from_pattern creates a pcre2_match_data object associated with the compiled pattern. This object stores the match result. The application passes it to pcre2_match together with the pattern, subject, subject length, starting offset, match options, and an optional match context.
The return value controls the next operation. PCRE2_ERROR_NOMATCH means that no match was found. Any other negative return value represents a matching error. A nonnegative return value indicates a match, and pcre2_get_ovector_pointer exposes an array of PCRE2_SIZE offsets. The first two offsets delimit the complete match; later pairs correspond to capture groups according to the pattern's capture structure.
The example prints the overall match by combining the first output vector pair with the original subject pointer. A fuller application can inspect the remaining pairs, but it must first establish how many captures exist and how each offset should be interpreted. An offset value of PCRE2_UNSET can occur when a capture group did not participate in the match, a case that an application should handle rather than treating every returned slot as a valid string range.
Memory ownership remains with the embedding application. The example frees match data with pcre2_match_data_free and the compiled pattern with pcre2_code_free. Early-return branches, repeated matches, and long-running processes need equivalent cleanup discipline, otherwise they can retain allocations that a short example would not expose.
Building the PCRE2 JIT configuration with CMake and Ninja
The README presents cloning a release tag as the scripted acquisition route. Its command relies on PCRE2_VERSION already identifying the intended release. After cloning, the example initializes the Git submodule before enabling JIT support.
git clone https://github.com/PCRE2Project/pcre2.git ./pcre2 \
--branch pcre2-$PCRE2_VERSION \
-c advice.detachedHead=false --depth 1
(cd ./pcre2; git submodule update --init)The checkout is shallow and detached by design. After acquisition, configure a Debug build with CMake and Ninja. The configuration requests the optional matching engine and places build products under build.
Building and linking the first eight-bit PCRE2 program
The README uses Ninja to complete the library build. Once that finishes, compile demo.c from the current directory, point the compiler at the generated headers, link against the build tree, and select the 8-bit library.
Running PCRE2 against a command-line subject
The complete quickstart compiles demo.c with gcc. The include path and library path point into ./pcre2/build, while -lpcre2-8 selects the 8-bit PCRE2 library. The resulting executable accepts a pattern and a subject.
gcc -g -I./pcre2/build -L./pcre2/build demo.c -o demo -lpcre2-8
./demo 'c.t' 'dogs and cats'The expected result for these arguments is a match beginning at the `c` in `cats`. Since `.` matches any character except a newline unless changed, the pattern spans `cat`, which is why Found match: 'cat' is the relevant output.
The demo source defines PCRE2_CODE_UNIT_WIDTH before including pcre2.h. That macro selects the public declarations for the eight-bit API. It then treats argv values as zero-terminated strings and passes strlen(subject) to pcre2_match. This is a real command-line use of the library, but it is not a general input-conversion layer.
The repository points to src/pcre2demo.c for a fuller example. Adopters should use that source as the first reference when they need command-line pattern handling, match iteration, capture reporting, or encoding-related behavior beyond the short demonstration.
JIT, Unicode, and code widths change integration decisions
The quickstart is explicitly an eight-bit build. Its source sets PCRE2_CODE_UNIT_WIDTH to 8, and its link command uses lpcre2-8. Applications whose strings use another representation cannot copy those details without resolving the corresponding code-unit width. The repository includes package metadata for 8-bit, 16-bit, and 32-bit libraries, but the quickstart does not give complete build and link examples for those variants.
Unicode support does not remove the need to choose a representation. The caller must know the encoding of the pattern and subject, compile with suitable options, and pass offsets in the code units expected by the selected build. The README states that PCRE2 accepts various character encodings, but pcre2_match does not receive a textual encoding name in the quickstart. Any required encoding detection or conversion remains outside that call.
JIT also affects acquisition and configuration. The quickstart initializes a Git submodule and sets -DPCRE2_SUPPORT_JIT=ON. A source archive must therefore be checked for any required submodule content before assuming it contains the complete JIT configuration. A consumer that does not need JIT can use a build without that option, although no performance claim should be attached to the choice without project-specific measurements.
A real alternative is the regular expression implementation supplied by the application's language runtime or standard library. A runtime may simplify deployment because its engine is already present, but it can constrain available patterns, representations, or tuning. PCRE2 instead offers a direct C interface, Perl-compatible syntax, Unicode support, separate code-unit widths, and optional JIT. The trade-off is that the embedding project owns native linking, build support, object cleanup, and upgrade compatibility.
Where PCRE2 is the wrong tool for a C project
PCRE2 is excessive when an application only needs substring checks or fixed replacement and an existing standard routine already provides those operations. Adding a regex engine creates another compiled dependency and requires code that compiles patterns, stores match data, checks return values, and releases resources. If those operations add no value to the product, the extra integration work has little justification.
Complex expressions can also create policy problems. The quickstart accepts a pattern from argv and calls pcre2_compile. It records an error number and error offset, but its failure branch prints only Invalid pattern. The README does not document a timeout, recursion limit, or pattern-complexity policy for this call. Applications that accept arbitrary user patterns must review the fuller PCRE2 documentation and their own resource controls rather than assuming the short example establishes safe limits.
The sample's use of strlen on the subject confirms its assumptions: the argument is interpreted as an eight-bit, zero-terminated string. It does not demonstrate how to process UTF-16, UTF-32, data containing embedded null code units, or subjects whose valid length is known separately from a terminator. Each case requires a deliberate API and library-width decision.
JIT availability should also be treated as optional. A source checkout that omits submodule content, a target with a build-system configuration that does not enable JIT, or a downstream package built without it may behave differently from the README's complete script. None of the repository files cited by the quickstart prove that every distribution enables the engine.
PCRE2 maintenance, upgrade work, and licence review
The repository is not archived, and its last push was on 2026-10-15. The listed releases include pcre2-10.49 on 2026-09-28, pcre2-10.48 on 2026-08-31, and pcre2-10.48-RC1 on 2026-08-25. Those dates show recent repository and release activity, but they do not remove integration work from each upgrade.
An embedding project should review ChangeLog and NEWS for the target release, then confirm that its compiler options, build files, and application tests still work. It should exercise successful and failed compilation, capture offsets, unmatched patterns, matching errors, and cleanup. Binary packaging also needs checking because library names and code-unit widths affect linking. Optional JIT configuration deserves a separate build check if it is part of the product.
The README describes PCRE2 as free and open-source under a BSD licence and says it can be used in proprietary software. However, GitHub classifies the repository licence as a custom licence that it cannot categorise and points to LICENCE.md. Repository files are the authoritative starting point for a licence review. Integrators should inspect LICENCE.md for the selected release and confirm any required notice or attribution text rather than relying only on the repository topic label.
The root-level SUPPORT-LIFECYCLE.md, SECURITY.md, and HACKING files may help integrators find policy or contributor information, but the README excerpt does not quote their contents. It would be incorrect to infer a support window, response time, or security policy from their filenames alone.
Editorial conclusion
Adopt PCRE2 when a C or C++ application needs Perl-compatible matching, Unicode support, selectable code-unit widths, or JIT compilation. Do not adopt it when simple fixed-string operations are sufficient or when managing an independent compiled library is an unreasonable cost. Inspect LICENCE.md, verify the character representation used by the application, and exercise capture, error, cleanup, and upgrade paths before shipping.
Frequently asked questions
What is PCRE2 used for?
PCRE2 is a C library for embedding regular expression pattern matching into applications. It supports Perl-compatible features, Unicode, multiple character encodings and code-unit widths, and an optional JIT engine.
How do I build PCRE2 with CMake and enable JIT?
Initialize the Git submodule, then configure PCRE2 with CMake and Ninja using -DPCRE2_SUPPORT_JIT=ON. Run cmake --build build/ to compile the configured library.
How do I link the first PCRE2 C program?
Set PCRE2_CODE_UNIT_WIDTH to 8 before including pcre2.h. The README links its 8-bit example with -lpcre2-8 and points the include and library paths at ./pcre2/build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pcre2project-pcre2)Was this useful?