Skip to Content
Course content

52: Regular Expressions in PHP (PCRE)

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I once spent an entire Tuesday afternoon writing a validation function for a proprietary part-number system. The format was specific: three uppercase letters, a hyphen, five digits, another hyphen, and two more uppercase letters (like ABC-12345-XY). I was using a combination of substr(), ctype_digit(), and a dozen nested if statements. It looked like a "ladder of doom." My senior dev looked at my forty lines of code, sighed, and replaced the whole thing with a single preg_match() call. I felt a mix of defeat and awe. That was the moment I realized that while regular expressions have a reputation for looking like "cat walking across a keyboard," they are the most powerful string-manipulation tools in your kit.

Taming the Pattern Syntax

In PHP, we use PCRE (Perl Compatible Regular Expressions). Most of your work will happen with preg_match(). The first thing you'll notice is that the pattern is wrapped in delimiters—usually forward slashes /. These aren't actually part of the regex itself; they just tell PHP where the pattern starts and ends.

Let's look at that part-number example. Instead of checking each character manually, we define a pattern: /^[A-Z]{3}-\d{5}-[A-Z]{2}$/. Here's the breakdown: ^ anchors the match to the start of the string, [A-Z]{3} looks for exactly three uppercase letters, \d{5} hunts for five digits, and $ ensures nothing comes after the final two letters. If you omit those anchors, PHP will return true even if the part number is buried inside a paragraph of text, which is usually not what you want for validation.

$partNumber = "ABC-12345-XY";
$pattern = '/^[A-Z]{3}-\d{5}-[A-Z]{2}$/';

if (preg_match($pattern, $partNumber)) {
    echo "Valid part number!";
} else {
    echo "Invalid format.";
}

Hunting for Multiple Matches and Capture Groups

Sometimes you aren't just checking if a string is valid; you're trying to extract specific pieces of data from a larger mess. This is where preg_match_all() and "capture groups" come in. By wrapping part of your regex in parentheses (), you're telling PHP, "I need to know if the whole thing matches, but I specifically want to save this piece for later."

Imagine you're scraping a raw text file for email addresses. You don't just want to know if the file contains emails; you want a list of every email found. I usually suggest starting with a simple pattern and refining it as you find edge cases—because regex is an iterative process. You'll almost certainly get it wrong the first time; just don't let it frustrate you.

$text = "Contact us at support@company.com or sales@company.com for help.";
$pattern = '/([a-z0-9._%+-]+)@([a-z0-9.-]+)\.([a-z]{2,})/';

preg_match_all($pattern, $text, $matches);

// $matches[0] contains the full emails
// $matches[1] contains just the usernames
// $matches[2] contains just the domains
print_r($matches[1]); // Output: Array([0] => support, [1] => sales)

Cleaning String Noise with Replacement

Finally, there's preg_replace(). This is my go-to for sanitizing user input. A common headache is dealing with phone numbers. Users enter them as (555) 123-4567, 555.123.4567, or 5551234567. If you try to use str_replace() for every possible separator, you'll be there all day.

Instead, you can use a character class to say, "Find anything that is NOT a digit and replace it with nothing." The ^ symbol inside the square brackets [^ ] acts as a negation. It's a clean, one-line way to strip all the noise and leave only the raw numbers, which is what your database actually cares about.

$phone = "(555) 123-4567";
$cleanPhone = preg_replace('/[^0-9]/', '', $phone);
echo $cleanPhone; // Output: 5551234567



📋 Practical Task

Exercise: Developing a Log File Entry Parser

You have been handed a raw server log file. Each line follows a specific format: [TIMESTAMP] LEVEL: Message. For example: [2023-10-01 12:00:01] ERROR: Database connection failed.

Write a PHP script that processes the following array of log entries:

$logs = [
    "[2023-10-01 12:00:01] ERROR: Database connection failed",
    "[2023-10-01 12:05:22] INFO: User logged in",
    "[2023-10-01 12:10:00] WARNING: Disk space low",
    "[2023-10-01 12:15:45] ERROR: API Timeout"
];

Your script must use preg_match() to loop through the logs and extract the Timestamp, the Level, and the Message into a structured associative array for each entry. Only entries that strictly match the format should be processed. Your final output should be an array of arrays, where each inner array contains the keys 'time', 'level', and 'message'.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.