iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

PHP PCRE

PHP’s regex API is PCRE: preg_match, preg_match_all, preg_replace, preg_replace_callback, preg_split. Patterns are strings with delimiters (e.g. /.../, #...#) and flags.

preg_* recipes that ship in real code

EXAMPLE
<?php
// 1) Match — preg_match returns 0 or 1; captures land in $m
$line = 'order id=12345 status=paid total=99.95';
if (preg_match('/id=(\d+)\s+status=(\w+)\s+total=([\d.]+)/', $line, $m)) {
    [$_, $id, $status, $total] = $m;
    // $id = '12345', $status = 'paid', $total = '99.95'
}

// 2) Match all — preg_match_all
$html = '<a href="/x">x</a><a href="https://y.com">y</a>';
preg_match_all('/href="([^"]+)"/', $html, $m);
// $m[1] = ['/x', 'https://y.com']

// 3) Replace
$slug = preg_replace('/[^a-z0-9]+/i', '-', strtolower('Hello, World!'));
// 'hello-world-'
$slug = trim($slug, '-');

// 4) Replace with callback — for context-dependent transforms
$text = preg_replace_callback(
    '/\b(\d{4})-(\d{2})-(\d{2})\b/',
    fn($m) => DateTime::createFromFormat('Y-m-d', $m[0])->format('j M Y'),
    'Booking on 2026-06-07 confirmed.'
);
// 'Booking on 7 Jun 2026 confirmed.'

// 5) Split
$parts = preg_split('/\s*,\s*/', 'a,  b,c , d');
// ['a', 'b', 'c', 'd']

// 6) Named groups — (?<name>...)
if (preg_match('/^(?<user>[^@]+)@(?<host>.+)$/', $email, $m)) {
    $user = $m['user'];
    $host = $m['host'];
}

// 7) Multiline + case-insensitive + extended whitespace
preg_match('/^ERROR:.*$/im', $log, $m);

// 8) Useful patterns
preg_match('/^[\w.+-]+@[\w-]+\.[\w.-]+$/', $input);                  // crude email
preg_match('/^https?:\/\/[^\s"<>]+$/', $url);                        // URL-ish
preg_match('/^[+]?[0-9 ()-]{7,20}$/', $phone);                       // loose phone
preg_match_all('/#\w+/', $tweet, $m);                                // hashtags

// 9) Catch a bad regex BEFORE it hits prod
if (@preg_match($pattern, '') === false) {
    throw new InvalidArgumentException('bad regex: ' . preg_last_error_msg());
}

// 10) Performance pitfalls
//   • Don't compile inside a tight loop — assign once, reuse
//   • Catastrophic backtracking — avoid `(a+)+`, use atomic groups (?>...) or possessive quantifiers (a++)
//   • For literal-string search, use strpos / str_contains — they're O(n) instead of regex's overhead

// 11) Replace multiple patterns in one call — arrays
$clean = preg_replace(
    ['/\s+/', '/[^\w -]/'],
    [' ',     ''],
    $dirty
);

Why it matters

preg_replace_callback is the most under-used PHP regex function — any replacement that depends on the capture (date reformatting, normalisation, escaping) is one line cleaner than a pre-pass and a second regex.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
if (preg_match('/(?P<area>\d{3})-(?P<num>\d{4})/', '555-867-5309', $m)) {
    echo $m['area'], ' ', $m['num'];
}
Try it Yourself »

Discussion

Loading…