Advanced Regular Expressions
19.1 Extended Mode and Readability
my $email_re = qr{
\A
(?<user> [\w.+-]+ ) # local part
@
(?<domain> [\w-]+ (?: \. [\w-]+ )+ ) # domain with at least one dot
\z
}x;
my $date_re = qr/(?<y>\d{4}) - (?<m>\d\d) - (?<d>\d\d)/x;
my $combined = qr/Date: \s* $date_re/x; # compose regexes19.2 Lookaround Assertions
'price: $100' =~ /(?<=\$)\d+/; # lookbehind: digits preceded by $
'foobar' =~ /foo(?=bar)/; # lookahead
'foobaz' =~ /foo(?!bar)/; # negative lookahead
'xbar' =~ /(?<!foo)bar/; # negative lookbehind
my $strong = qr/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$/; # password rule via lookaheads
(my $n = '1234567') =~ s/(?<=\d)(?=(?:\d{3})+$)/,/g; # "1,234,567"19.3 Backtracking Control, Atomic Groups and Performance
Avoid catastrophic backtracking ((a+)+b on long strings). Use anchors, specific classes, and possessive/atomic constructs.
use re 'debug'; shows how a regex compiles and executes. use re qw(regexp_pattern is_regexp); gives introspection.
/(?>\d+)\./ # atomic group: no backtracking into it
/\d++\./ # possessive quantifier (same effect)
/a(*SKIP)(*FAIL)|b/ # backtracking control verbs: skip "a" contexts19.4 Recursion, Conditionals and Code
my $balanced = qr/ \( (?: [^()]++ | (?R) )* \) /x; # recursive: balanced parentheses
say 'balanced' if '(a(b)c)' =~ /^$balanced$/;
my $re = qr/ (?<pair> \[ (?: [^\[\]]++ | (?&pair) )* \] ) /x; # named recursion
/^(<)?\w+(?(1)>)$/ # conditional: if group 1 matched, require ">"
my $cnt = 0;
'aaa' =~ /(?:a(?{ $cnt++ }))*/; # embedded code (use sparingly)19.5 The \G Anchor and Lexing
/c keeps pos() after a failed match. \G anchors to where the last match ended. Together they make a simple lexer.
my $input = 'x = 42 + y';
my @tokens;
pos($input) = 0;
while (pos($input) < length $input) {
if ($input =~ /\G\s+/gc) { next }
elsif ($input =~ /\G([a-z]\w*)/gc) { push @tokens, [IDENT => $1] }
elsif ($input =~ /\G(\d+)/gc) { push @tokens, [NUM => $1] }
elsif ($input =~ /\G([=+\-*\/])/gc) { push @tokens, [OP => $1] }
else { die "Unexpected char at " . pos($input) }
}19.6 Regex Modules
Regexp::Common (ready-made patterns: numbers, IPs, URIs), Regexp::Assemble / Regexp::Trie (combine many words efficiently), Regexp::Grammars (full grammars in regex), Parse::RecDescent / Marpa::R2 (parsers), re::engine::PCRE2 (swap the engine).