Shape / columns · All operations

Match with a regular expression

Regex extract, match, replace.

Status

In arcform

Runs as a SQL step

arcform carries it as a sql: step today.

Shape of the result
one row out per row in, with columns added or changed
Level
one clause of SQL

The DuckDB step

Extract named groups

It reads the orders table the proofs share. Create it first:

SQL
CREATE TABLE orders AS SELECT * FROM (VALUES
  (1,  'Alice Ng',      'north', DATE '2026-01-03', 120.00, 'widget', 'a|b',   '{"channel":"web","items":[1,2]}'),
  (2,  'alice ng',      'north', DATE '2026-01-05',  80.50, 'gadget', 'b',     '{"channel":"shop","items":[3]}'),
  (3,  'Bob  Okafor',   'south', DATE '2026-01-05', 300.00, 'widget', 'a|c',   '{"channel":"web","items":[4,5,6]}'),
  (4,  'Carla Díaz',    'east',  DATE '2026-01-09',  NULL,  'gizmo',  NULL,    '{"channel":"web","items":[]}'),
  (5,  'Bob Okafor',    'south', DATE '2026-01-12',  45.25, 'gadget', 'c',     '{"channel":"phone","items":[7]}'),
  (6,  'Dev Patel',     'west',  DATE '2026-01-12', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (7,  'Carla Diaz',    'east',  DATE '2026-01-20',  99.99, 'gizmo',  'b|c',   '{"channel":"shop","items":[10]}'),
  (8,  'Dev Patel',     'west',  DATE '2026-02-02', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (9,  'Eve Larsen',    NULL,    DATE '2026-02-03',  15.00, 'gadget', NULL,    '{"channel":"web","items":[11]}'),
  (10, 'Alice Ng',      'north', DATE '2026-02-10', 220.00, 'gizmo',  'a|b|c', '{"channel":"phone","items":[12,13]}')
) t(order_id, customer, region, order_date, amount, product, tags, meta);

Then run the statement:

SQL
CREATE TEMP TABLE result AS
SELECT order_id, order_date::VARCHAR AS s, regexp_extract(order_date::VARCHAR, '(\d+)-(\d+)-(\d+)', ['y','m','d']) AS parts FROM orders;
SELECT * FROM result;
SELECT CASE WHEN ((SELECT max(parts.y) = '2026' AND max(parts.m) FILTER (WHERE order_id = 10) = '02' AND max(parts.d) FILTER (WHERE order_id = 10) = '10' FROM result)) THEN 'as expected' ELSE error('the date did not come apart into year, month and day') END AS verdict;
  • It needs nothing installed beyond DuckDB itself.
  • The statement checks its own result and raises an error when it is wrong: “the date did not come apart into year, month and day”.
  • It passed on DuckDB v2.0.0 (Cyanoptera) d54cbbe3df.

Variants

Test for a pattern match

Test whether, or count how often, a value matches a regular expression or LIKE pattern.

What other tools call it

Meridian's classification; an independent blind rating agreed on 86.2% of 312 rows (exact class, version 2).

Alteryx Designer (1)
  • RegExread 2026-09-27

    Parse, match, tokenise or replace text with a regular expression

Apache DataFusion (1)
Apache Hop (1)
  • Regex Evaluationread 2026-09-27

    Match a field against a regular expression and extract capture groups to new fields

Apache NiFi (4)
  • ExtractGrokread 2026-09-27

    Match content against Grok expressions; results go to attributes or replace content as JSON

  • ExtractTextread 2026-09-27

    Evaluate regular expressions against content and write the matches to attributes

  • ReplaceTextread 2026-09-27

    Replace content matched by a regular expression or literal with a replacement value

  • Searchingread 2026-09-27

    13 functions: startsWith, endsWith, contains, in, find, …

Apache SeaTunnel (1)
  • RegexExtractread 2026-09-27

    Extract regex capture groups from a field into new fields, with defaults when nothing matches

AWS Glue (1)
DuckDB (2)
Duckle (3)
  • Regex Extractread 2026-09-25

    extract a capture group with regexp_extract

  • Regex Matchread 2026-09-25

    boolean column: does the regex match

  • Regex Replaceread 2026-09-25

    regex replace in a column

EasyMorph (1)
  • Regular expressionread 2026-09-27

    Add a column holding the regular-expression matches found in a text column

Ibis (6)
  • RegexExtractread 2026-09-27

    Extract a capture group of a regular expression from a string

  • RegexReplaceread 2026-09-27

    Replace matches of a regular expression in a string

  • RegexSearchread 2026-09-27

    Test whether a string matches a regular expression

  • RegexSplitread 2026-09-27

    Split a string into an array at matches of a regular expression

  • StringSQLILikeread 2026-09-27

    Match a string against a SQL LIKE pattern, ignoring case

  • StringSQLLikeread 2026-09-27

    Match a string against a SQL LIKE pattern

KNIME Analytics Platform (1)
  • Split a string column into columns, one per capture group of a regular expression

OpenRefine (2)
Pentaho Data Integration (1)
  • Regex Evaluationread 2026-09-27

    Test a field against a regular expression and extract capture groups to new fields

Polars (2)
RapidMiner Studio (5)
  • Keep Document Partsread 2026-09-27

    Keep only the first part of each token that matches a regular expression

  • Remove Document Partsread 2026-09-27

    Delete the parts of a document that match a regular expression

  • Replaceread 2026-09-27

    Replace the parts of nominal values matching a regular expression

  • Replace (In Database)read 2026-09-27

    Replace the parts of string values matching a regular expression, executed in the database

  • Replace Tokensread 2026-09-27

    Regex find-and-replace within each token

Talend (3)
  • tExtractRegexFieldsread 2026-09-27

    Split a formatted string column into several columns by regex matching

  • tPatternExtractread 2026-09-27

    Extract from a column the strings that match a Java regular expression

  • tStandardizeRowread 2026-09-27

    Tokenise text and apply parser rules, writing the tagged and standardised parts as XML or JSON

Trifacta (9)
VisiData (8)
  • addcol-captureread 2026-09-23

    Add column from regex capture groups of current column

  • addcol-regex-substread 2026-09-23

    Add column replacing regex matches in current column, with backreferences

  • addcol-substread 2026-09-23

    (deprecated) Add column replacing regex matches in current column

  • capture-colread 2026-09-23

    (deprecated) Add columns from regex capture groups of current column

  • setcol-regex-substread 2026-09-23

    Replace regex matches in current column for selected rows

  • setcol-regex-subst-allread 2026-09-23

    Replace regex matches in all visible columns for selected rows

  • setcol-substread 2026-09-23

    (deprecated) Replace regex matches in current column for selected rows

  • setcol-subst-allread 2026-09-23

    (deprecated) Replace regex matches in all visible columns for selected rows

Background

A regular expression is a sequence of characters that specifies a match pattern in text, usually used to find, find and replace, or validate strings.[1] Common applications of regular expressions include data validation, data scraping, data wrangling and simple parsing.[1]

When to use it

In DuckDB, regexp_matches returns true if the string merely contains the pattern, unless the tokens ^ and $ anchor the pattern to the start and end of the string.[2] In DuckDB, regexp_full_match returns true only if the entire string matches the regular expression.[2] When a regular expression is used to validate a column, anchor it or use a full-match test, so that a value which merely contains a valid fragment is not passed as valid. (Meridian's view)

A regular expression denial of service (ReDoS) is an attack that supplies a regular expression or an input that takes a long time to evaluate, exploiting the super-linear worst-case complexity of many implementations.[3] In PostgreSQL, regular expressions can be contrived that take arbitrary amounts of time and memory to process, so patterns from hostile sources call for wariness and, if they must be accepted, a statement timeout.[4] DuckDB uses the RE2 library as its regular expression engine.[2] RE2 was designed to handle regular expressions from untrusted users without risk, and one of its primary guarantees is that match time is linear in the length of the input string.[5] Where a pattern comes from a user rather than from the analyst writing the query, prefer an engine with a linear-time guarantee, or set a time limit. (Meridian's view)

Different syntaxes for writing regular expressions have existed since the 1980s, one of them the widely used Perl syntax.[1] Starting in 1997, Philip Hazel developed Perl Compatible Regular Expressions (PCRE), which attempts to closely mimic Perl's regex functionality.[1] RE2's syntax is, roughly speaking, a subset of that accepted by PCRE, with various caveats.[6] PostgreSQL's regular expressions are implemented using a software package written by Henry Spencer.[4] RE2 does not support constructs for which only backtracking solutions are known to exist, so backreferences and look-around assertions are not supported.[5] Test a pattern copied from another tool in the engine that will run it, rather than assuming the dialects agree. (Meridian's view)

In Python and some other implementations, such as Java, the quantifiers *, + and ? are greedy by default because they match as many characters as possible.[1] In RE2, x+ matches one or more x and prefers more, while x+? matches one or more x and prefers fewer.[6]

The method

Regular expressions originated in 1951, when mathematician Stephen Cole Kleene described regular languages using his mathematical notation called regular events.[1] Ken Thompson built Kleene's notation into the editor QED as a means to match patterns in text files, and later added the capability to the Unix editor ed, which eventually led to grep's use of regular expressions.[1] Thompson's construction algorithm builds a nondeterministic finite automaton (NFA) from a regular expression, and Thompson first described a way of translating regular expressions into NFAs in a 1968 paper.[1][7]

There are at least three different algorithms that decide whether and how a given regular expression matches a string.[1] A deterministic finite automaton (DFA) built explicitly from a regular expression of size m costs O(2^m) in time and memory to construct, but runs on a string of size n in O(n) time.[1] Simulating the NFA directly keeps the DFA implicit and avoids the exponential construction cost, but the running cost rises to O(mn).[1] Matching by backtracking can take exponential time, which simple implementations show on expressions like (a|aa)*b that contain both alternation and unbounded quantification.[1] Any implementation that allows backreferences, or implements the various extensions introduced by Perl, must include some kind of backtracking.[1] A backreference like \1 matches the string matched by a previous parenthesised expression, so (cat|dog)\1 matches catcat and dogdog but not catdog nor dogcat.[7] RE2 evaluates all alternatives in parallel, where a backtracking engine tests each alternative sequentially.[5]

Compared with the alternatives

In PostgreSQL, a LIKE pattern always covers the entire string, whereas a regular expression may match anywhere within a string unless it is explicitly anchored to the beginning or end.[4] In PostgreSQL, the SIMILAR TO operator interprets its pattern using the SQL standard's definition of a regular expression.[4] In PostgreSQL, SIMILAR TO, like LIKE, succeeds only if its pattern matches the entire string.[4] In PostgreSQL, LIKE searches, being much simpler than SIMILAR TO and regular expressions, are safer to use with possibly hostile pattern sources.[4] Before regular expressions, many search languages allowed simple wildcards such as * for any sequence of characters and ? for a single character, relics of which survive in glob syntax for filenames and in the SQL LIKE operator.[1] Where a fixed prefix, a fixed suffix or a simple wildcard says what is needed, LIKE is the plainer choice; a regular expression earns its place when the pattern needs alternation, repetition or groups. (Meridian's view)

Used in

4 Protocols use this operation: