use v5.12; use warnings; use Data::Dump; my $str = 'a 1 2 3 b 4 5 6'; my $re_start = qr{(?\w+)\s*}; my $re_repeat = qr{\s*(?\d+)\s*}; # --- approach 1 with \G and /gc my @res1; while ( $str =~ /\G$re_start/g ) { push @res1, [$+{start}]; while ($str =~ /\G$re_repeat/gc) { push @{ $res1[-1] }, $+{repeat}; } } dd \@res1; # --- approach 2 with embedded (?{CODE}) my @res2; $str =~ / (?: $re_start (?{ push @res2, [$+{start}] }) (?: $re_repeat (?{ push @{ $res2[-1] }, $+{repeat} }) )* )* /gx; dd \@res2;