← Perl EnglishChapter 08 of 13

Regular Expressions

## Learning Objectives - Master pattern matching - Use substitutions and transliterations - Work with qr// for compiled patterns - Understand regex modifiers - Master regex quoting ## Basic Matching ### =~ Operator ```perl use strict; use warnings; my $text = "Hello, World!"; if ($text =~ /World/) { print "Found!\n"; } my $found = $text =~ /World/; # 1 or undef ``` ### Matching with Variables ```perl my $pattern = "World"; my $text = "Hello, World!"; if ($text =~ /$pattern/) { print "Matched!\n"; } ``` ### Default Variable $_ ```perl use strict; use warnings; $_ = "Hello, World!"; if (/World/) { print "Found in \$_\n"; } print "Found" if /World/; ``` ## Regex Modifiers ### Common Modifiers ```perl my $text = "Hello WORLD"; /world/i; # i - Case insensitive /HELLO/i; # Matches "HELLO", "hello", "Hello", etc. my $multiline = "line1\nline2\npattern\nline4"; $multiline =~ /^pattern/m; # m - Multiline (^ matches line starts) my $file_content = "first\nsecond\nthird"; $file_content =~ /\Afirst/; # \A matches absolute start $file_content =~ /\zthird/; # \z matches absolute end ``` ### Extended Modifiers ```perl my $text = "Comment line\n indented code"; $text =~ /^\s+#\s+(\w+)/x; # x - Extended (allow whitespace and comments) my $balanced = "((a + b) * c)"; $balanced =~ /\((?:[^()]++|\([^()]*\))+\)/; # + - Possessive (no backtrack) my $str = "a\nb\nc"; $str =~ /a.*\n.*\n.*/s; # s - Single line (. matches \n) ``` ## Character Classes ### Basic Classes ```perl /[abc]/; # a, b, or c /[^abc]/; # NOT a, b, or c /[a-z]/; # lowercase letter /[A-Z]/; # uppercase letter /[0-9]/; # digit /[a-zA-Z0-9]/; # alphanumeric ``` ### Shorthand Classes ```perl /\d/; # Digit [0-9] /\D/; # Non-digit [^0-9] /\w/; # Word char [a-zA-Z0-9_] /\W/; # Non-word char /\s/; # Whitespace [ \t\n\r\f] /\S/; # Non-whitespace ``` ### Examples ```perl my $phone = "123-456-7890"; if ($phone =~ /\d{3}-\d{3}-\d{4}/) { print "Valid phone\n"; } my $ip = "192.168.1.1"; if ($ip =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { print "Looks like IP\n"; } ``` ## Quantifiers ### Basic Quantifiers ```perl /a*/; # Zero or more a's /a+/; # One or more a's /a?/; # Zero or one a /a{3}/; # Exactly 3 a's /a{3,}/; # Three or more a's /a{3,5}/; # Between 3 and 5 a's ``` ### Greedy vs Minimal ```perl my $html = "bold and italic"; $html =~ /<.+>/; # Greedy: matches everything $html =~ /<.+?>/; # Minimal: matches ... then ... my $text = "abc123def"; $text =~ /\d+/; # "123" (greedy) $text =~ /\d+?/; # "1" (minimal) $text =~ /\d*?/; # "" (zero is minimal match) ``` ## Anchors ### Position Anchors ```perl /^abc/; # Start of string (or line with /m) /abc$/; # End of string (or line with /m) /\A/; # Absolute start of string /\z/; # Absolute end of string /\b/; # Word boundary /\B/; # Non-word boundary ``` ### Word Boundaries ```perl my $text = "the them theme"; $text =~ /\bthe\b/; # Matches "the" but not "them" or "theme" $text =~ /\Bthe\B/; # Matches "the" in "theme" but not standalone ``` ## Capturing Groups ### Basic Capturing ```perl my $date = "2024-01-15"; if ($date =~ /(\d{4})-(\d{2})-(\d{2})/) { print "Year: $1\n"; # 2024 print "Month: $2\n"; # 01 print "Day: $3\n"; # 15 } ``` ### Non-Capturing Groups ```perl my $text = "abc123def"; # Capturing if ($text =~ /(\d+)/) { print "Number: $1\n"; # 123 } # Non-capturing (?:...) if ($text =~ /(?:abc)(\d+)/) { print "Number: $1\n"; # 123 (still $1, abc is not captured) } ``` ### Named Captures ```perl use 5.010; my $date = "2024-01-15"; if ($date =~ /(?\d{4})-(?\d{2})-(?\d{2})/) { print "$+{year}-$+{month}-$+{day}\n"; } ``` ## Alternation ### Basic Alternation ```perl my $color = "blue"; if ($color =~ /red|green|blue/) { print "Primary color or blue\n"; } my $extension = "txt"; if ($extension =~ /jpg|png|gif|bmp/) { print "Image file\n"; } ``` ### Precedence ```perl # | has low precedence /my (dog|cat)s are (cute|fast)/; # Correct # vs grouping /my (dogs|cats) are (cute|fast)/; ``` ## Backreferences ### Matching Repeated Characters ```perl # Match quoted strings (single or double) my $text = "'hello' and \"world\""; if ($text =~ /(['"])(.*?)\1/) { # \1 matches same quote print "Quoted: $2\n"; } ``` ### Backreferences in Patterns ```perl # Match repeated word my $sentence = "the the cat"; if ($sentence =~ /\b(\w+)\s+\1\b/) { print "Repeated: $1\n"; # "the" } ``` ## Substitutions ### Basic Substitution ```perl my $text = "Hello World"; $text =~ s/World/Perl/; print $text; # "Hello Perl" # In-place with return value my $new = $text =~ s/World/Perl/r; ``` ### Global Substitution ```perl my $text = "aaa bbb aaa ccc"; $text =~ s/aaa/bbb/g; # All occurrences print $text; # "bbb bbb bbb ccc" # Case-insensitive global my $words = "Apple apple APPLE"; $words =~ s/apple/fruit/gi; # All, case-insensitive ``` ### Multiple Substitutions ```perl my $text = "hello world"; $text =~ s/hello/hi/r =~ s/world/perl/r =~ s/hi/perl/r; # Chaining (returns final result) ``` ## Transliteration (tr///) ### Basic tr ```perl my $text = "hello"; $text =~ tr/a-z/A-Z/; # "HELLO" my $dna = "ACGT"; $dna =~ tr/ACGT/TGCA/; # "TGCA" ``` ### tr/// vs s/// ```perl # tr/// - character by character "abab" =~ s/ab/cd/g; # "cdcd" (substitution) /ab/ab/cd/g; # "cdcd" (substitution) /ab/cd/g; # "cdcd" (transliteration) # s/// - regex substitution "abab" =~ s/ab+/cd/g; # "cdcd" (replaces 'ab' with 'cd') ``` ### Counting with tr ```perl my $text = "hello world"; my $count = ($text =~ tr/o//); # 2 print "Found $count o's\n"; # Delete my $clean = $text =~ tr/a-z//cdr; # Remove non-letters ``` ## qr// Compiled Patterns ### Basic Usage ```perl my $pattern = qr/\d{3}-\d{4}/; if ("123-4567" =~ $pattern) { print "Match!\n"; } if ("123-456-7890" =~ $pattern) { print "Also matches!\n"; # Partial match } ``` ### Combining Patterns ```perl my $digit = qr/\d+/; my $hyphen = qr/-/; my $phone = qr/^$digit$hyphen$digit$/; "123-456" =~ $phone; # Matches ``` ### With Modifiers ```perl my $case_insensitive = qr/hello/i; my $multiline = qr/^hello/im; my $compiled = qr/hello\s+world/ix; ``` ## Split with Regex ```perl my $text = "one,two,three"; my @parts = split /,/, $text; # ("one", "two", "three") my $date = "2024-01-15"; my ($year, $month, $day) = split /-/, $date; # With limit my @words = split /\s+/, "one two three", 2; # ("one", "two three") # Split on regex my $line = "abc123def456ghi"; my @nums = split /\D+/, $line; # ("", "123", "456", "ghi") ``` ## Global Matches ### Matching All Occurrences ```perl my $text = "abc123def456"; my @matches = $text =~ /\d+/g; print "@matches\n"; # "123" "456" # With capturing my @all_numbers = $text =~ /(\d+)/g; print "@all_numbers\n"; # "123" "456" ``` ### Iteration ```perl my $text = "Price: \$100, Discount: \$50"; while ($text =~ /\$\d+/g) { print "Found: $&\n"; # $& is the matched string } # With captures while ($text =~ /(\$)(\d+)/g) { print "Currency: $1, Amount: $2\n"; } ``` ## Special Variables ```perl $& # Entire matched string $` # String before match $' # String after match $1 # First capture $2 # Second capture $+ # Last capture $+{name} # Named capture (5.10+) ``` ## Lookahead and Lookbehind ### Lookahead ```perl # Positive lookahead (?=...) my $text = "foobar"; if ($text =~ /foo(?=bar)/) { } # Match "foo" only if followed by "bar" # Negative lookahead (?!...) if ($text =~ /foo(?!bar)/) { } # Match "foo" only if NOT followed by "bar" ``` ### Lookbehind ```perl # Positive lookbehind (?<=...) my $price = "\$100"; if ($price =~ /(?<=\$)\d+/) { } # Match digits after "$" # Negative lookbehind (?...)` - Alternation with `|` - Substitution: `s/pattern/replacement/g` - Transliteration: `tr///` for character mapping - `qr//` compiles patterns for reuse - Modifiers: `/i`, `/g`, `/m`, `/s`, `/x` - Global matching with `/g` returns all matches

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →