regexp_match
PG 10+→ text[]Returns the first matching substring(s) for a POSIX regex pattern. Returns NULL if no match, or a text array of capture groups.
Signature
regexp_match ( string text, pattern text [, flags text] ) → text[]Parameters
| Parameter | Type | Description |
|---|---|---|
| string | text | Input string to search |
| pattern | text | POSIX regular expression |
| flags | text | Optional flags: i=case-insensitive, g=global (use regexp_matches for multiple), n=newline-sensitive, s=dot matches newline |
Examples
SELECT regexp_match('abc123', '[0-9]+');{123}SELECT regexp_match('user@example.com', '([^@]+)@(.+)');{user,example.com}SELECT (regexp_match(log, 'duration: ([0-9.]+) ms'))[1]::numeric FROM logs;Extracted duration valueSELECT COALESCE((regexp_match(event_text, 'user_id=(\d+)'))[1], '0')::int AS user_id FROM events;Parsed user_id integer, 0 if missingregexp_matches returns SETOF text[], which means it acts as a set-returning function and can multiply rows in a SELECT list in unexpected ways. When you only want the first match, use regexp_match (PG 10+) instead — it returns a single text[] row or NULL.
✓ Instead: -- Avoid: regexp_matches without 'g' flag in a SELECT list SELECT id, (regexp_matches(col, 'pattern'))[1] FROM t; -- Prefer: regexp_match for single-match extraction SELECT id, (regexp_match(col, 'pattern'))[1] FROM t;
Use `(regexp_match(str, pattern))[n]` to extract the nth capture group. Index 1 is the first group. Wrap in COALESCE to handle non-matching rows.
SELECT COALESCE((regexp_match(url, 'https?://([^/]+)'))[1], 'unknown') AS domain FROM page_views;Domain extracted from URL, 'unknown' if no match