Regular Expression Basics

18.1 Matching

use v5.36;
my $text = 'The year 2025 was great; 2026 will be better.';

if ($text =~ /year (\d{4})/) {          # match operator m// (the m is optional with //)
    say "Found year: $1";               # $1, $2 ... capture groups
}
say 'No digits' if $text !~ /\d/;
my @years = $text =~ /(\d{4})/g;        # list context + /g: all matches
my ($first) = $text =~ /(\d+)/;         # first capture
while ($text =~ /(\d{4})/g) {           # scalar context + /g: iterate
    say "Year $1 at position ", pos($text);
}
for (@lines) { say if /error/i }        # matches against $_ by default
my $re = qr/\b(\w+)@(\w+\.\w+)\b/;      # precompiled regex object
if ('[email protected]' =~ $re) { say "user=$1 domain=$2" }

18.2 Regex Syntax Summary

Any character except newline (any character with /s) Digit, word character, whitespace [abc] / [^abc] / [a-z]

Start/end of string (of a line with /m) \A / \z / \Z

Absolute start / end / end before a final newline Word boundary / non-boundary 0+, 1+, 0 or 1 (greedy) {n} {n,} {n,m} Exact / at least / range *? +? ?? {n,m}? Non-greedy (lazy) Possessive (no backtracking) \1, \g1, \g{-1} \p{L} / \p{Lu} / \p{Greek}

18.3 Modifiers

Global (all matches) Multiline: ^ and $ match at line boundaries Single-line: . matches newline

Extended: whitespace and comments allowed in the pattern Compile once (obsolete; use qr//)

Evaluate the replacement as code (in s///) Return the modified string, leaving the original unchanged (in s///, tr///) Make plain () non-capturing (5.22+) /a / /aa / /u / /l

ASCII-restrict \d\w\s / Unicode rules / locale rules Preserve ${^MATCH} and friends (default behavior in modern Perl)

18.4 Substitution and Transliteration

my $s = 'Hello World';
$s =~ s/World/Perl/;                       # replace the first match
$s =~ s/o/0/g;                             # replace all
(my $copy = $s) =~ s/l/L/g;                # copy, then modify the copy
my $new = $s =~ s/\s+/_/gr;                # /r returns a new string (5.14+)
$s =~ s/(\w+)/\u$1/g;                      # capitalize each word
$s =~ s/(\d+)/$1 * 2/ge;                   # /e: replacement is Perl code
$s =~ s{^\s+|\s+$}{}g;                     # alternative delimiters
my $count = ($text =~ s/foo/bar/g);        # returns the number of substitutions
(my $t = $s) =~ tr/a-z/A-Z/;               # transliterate characters
my $vowels = ($s =~ tr/aeiouAEIOU//);      # count characters
$s =~ tr/a-zA-Z//cd;                       # delete everything except letters (/c complement, /d delete)
$s =~ tr/ //s;                             # squeeze repeated spaces

18.5 Captures and Match Variables

if ('2025-10-24' =~ /^(\d{4})-(\d{2})-(\d{2})$/) {
    my ($y, $m, $d) = ($1, $2, $3);
}
if ('2025-10-24' =~ /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/) {
    say "Year: $+{year}, Month: $+{month}";   # named captures in %+
}
my ($y, $m, $d) = '2025-10-24' =~ /(\d+)-(\d+)-(\d+)/;   # list assignment (preferred)
# $& (match), $` (prematch), $' (postmatch): safe to use in modern Perl (no global slowdown since 5.20)
# @- and @+: offsets of the match and groups