Advanced Regular Expressions
🔬 Advanced Regular Expressions
m//, s///, tr///, and basic capture groups. This chapter goes into the features that made Perl's regex engine the template PCRE was built from in the first place: lookaround assertions, named captures, and the readability-focused /x mode.
👀 Lookahead & Lookbehind
Lookaround assertions check that something is (or isn't) present next to a match — without actually including it in the matched text itself.
The key idea: lookaround asserts context without consuming it — the surrounding text is checked, but only what's inside the actual capturing parentheses ends up in the match. This is genuinely more precise than trying to capture-and-discard the surrounding text manually.
Perl's lookbehind (by default) requires the assertion to match a fixed number of characters — (?<=\$) (one character) is fine, but something like (?<=\d+) (a variable-length run of digits) raises Variable length lookbehind not implemented in many contexts. This is a real, common limitation to run into once you reach for lookbehind on anything beyond a short, fixed pattern — lookahead has no such restriction.
🏷️ Named Captures
(?<name>...) names a capture group, retrievable afterward through the special hash %+ as $+{name}. This is a genuine readability upgrade over Course 1's $1/$2/$3 — the code reads as "the date," "the level," "the message" directly, and reordering or adding groups elsewhere in the pattern doesn't silently renumber and break every existing reference the way inserting a new plain capture group would with $1-style captures.
📖 The /x Extended Mode
/x tells Perl to ignore whitespace in the pattern (unless explicitly escaped or inside a character class) and allows # comments directly inside it — turning a dense, hard-to-read pattern into something closer to documented code:
Every meaningful space in the pattern that needs to match a literal space has to be written as \s or \ (escaped) under /x, since plain whitespace in the pattern is now ignored — a real trade-off, but for anything beyond a short pattern, the readability gain from being able to comment each piece is substantial.
⚡ Other Useful Advanced Features
A greedy quantifier (+, *) consumes as much as it can before backtracking to satisfy the rest of the pattern; appending ? (+?, *?) flips it to match as little as possible instead — genuinely important the moment a pattern spans multiple delimiters, exactly the <a><b> case above.
🔧 A Worked Example — Validating and Parsing a Password
Each (?=...) lookahead checks a requirement independently, from the same starting position (lookahead doesn't advance the match position), without any of them consuming characters the others need to also see — this is a genuinely idiomatic way to validate "must contain X, and Y, and Z, in any order" with a single regex rather than several separate checks.
Lookaround: Perl vs. regex1's POSIX Regex
The site's own Learning Regular Expressions course (grep/sed/awk, POSIX BRE/ERE) has no lookaround support at all without reaching for GNU-specific extensions — POSIX regex simply wasn't designed with it. This is a concrete, practical instance of Course 1 Chapter 6's point that PCRE (adopted by countless other tools) grew directly out of Perl's own regex engine specifically because Perl supported features like this natively, years before they became commonplace elsewhere.
Lookahead / lookbehind
(?=...)/(?!...) and (?<=...)/(?<!...) — assert without consuming.
Named captures
(?<name>...), retrieved via $+{name} — more maintainable than $1.
/x mode
Ignores whitespace, allows # comments — turns a dense pattern into readable code.
Greedy vs. non-greedy
+?/*? match as little as possible, instead of as much as possible.
💻 Coding Challenges
Challenge 1: Extract Prices Without the Currency Symbol
Given my $text = "Items: $12, $8, $45";, use a lookbehind to extract just the numbers (not the $) into a list, and print them.
Challenge 2: Named Captures for a Date
Given my $date = "2026-07-10";, use named captures (?<year>, ?<month>, ?<day>) to extract each part, and print them as "Year: 2026, Month: 07, Day: 10" using %+.
Challenge 3: Rewrite with /x
Take the regex /^(\w+)@(\w+\.\w+)$/ (a simple email matcher) and rewrite it using /x mode with a comment explaining each piece, keeping its matching behavior identical.
🎯 What's Next
Next chapter: Context Deep Dive — wantarray, and scalar vs. list context edge cases, rigorously revisited from Course 1's introduction to the topic.