Advanced Regexes and Match Objects

28.1 Match Objects

my $m = 'John Smith, age 42' ~~ / $<first>=(\w+) \s+ $<last>=(\w+) ',' \s* 'age' \s* $<age>=(\d+) /;
say $m;                     # pretty tree of the match
say ~$m<first>, ' ', +$m<age>;     # John 42 (~ stringify, + numify)
say $m.from, ' ', $m.to, ' ', $m.prematch.raku, ' ', $m.postmatch.raku;
say $m.hash.keys.sort;      # (age first last)
say $m.caps».key;           # named/positional captures in order
my ($first, $last) = ($m<first>, $m<last>)».Str;

# Repeated captures produce arrays
if 'a=1, b=2, c=3' ~~ / [ (\w) '=' (\d) ]+ % [',' \s*] / {
    say $0».Str, ' ', $1».Str;     # (a b c) (1 2 3)
}

28.2 Named Regexes, Tokens and Rules

my regex  word-r  { \w+ }                 # regex: backtracking allowed
my token  number  { \d+ ['.' \d+]? }      # token: :ratchet (no backtracking)
my rule   assign  { <ident> '=' <number> }   # rule: :ratchet + :sigspace (whitespace matches <.ws>)
say 'x = 3.14' ~~ / <assign> /;
say ~$/<assign><number>;                  # 3.14
my token ipv4-octet { (\d**1..3) <?{ $0 <= 255 }> }   # code assertion
my token ipv4 { <ipv4-octet> ** 4 % '.' }
say '192.168.1.1' ~~ /^ <ipv4> $/ ?? 'valid' !! 'invalid';
say '999.1.1.1' ~~ /^ <ipv4> $/ ?? 'valid' !! 'invalid';

28.3 Longest Token Matching (LTM)

say ~('forest' ~~ / for | forest /);      # forest: | picks the longest matching alternative
say ~('forest' ~~ / for || forest /);     # for: || picks the first matching alternative

28.4 Interpolation, Code and Backreferences

my $word = 'cat';
say 'concatenate' ~~ / $word /;           # literal interpolation of a variable
my @alts = <dog cat bird>;
say 'a bird' ~~ / @alts /;                # alternation over array elements (LTM)
my $pattern = '\d+';
say 'abc 123' ~~ / <$pattern> /;          # interpolate a string as a regex
say 'abab' ~~ / (ab) $0 /;                # backreference
say 'xyzx' ~~ / (\w) :my $first = ~$0; \w* $first /;   # :my declares a lexical inside the regex
say 'aaa' ~~ m:ex/ a+ /;                  # exhaustive matching
say 'abcd'.match(/ \w\w /, :ov)».Str;     # overlapping: (ab bc cd)