use 5.014; # needs (?^mods:pattern) -- also // and s///p from 5.10 use warnings; use strict; my @baza_tek = ( [ '(?^u:ip(\d))' => 'int pro-$1$2' ], [ '(?^u:iipp(\d))' => 'inet proto-$1' ], [ '(?^u:zot(\d))' => 'bang-$2' ], [ '(?^u:zero)' => 'nada-$1' ], [ '(?^u:foo(\d)(\d)?(x))' => 'boo far-$1$2' ], [ '(?^u:udp(\d))' => 'datagram-$1' ], [ '(?^u:NOTHING(\d))' => 'internet protocol-$1' ], # [ '(?^u:BADREGEX+++)' => 'bad regex - match fails' ], ); LINE: while (my $line = ) { chomp $line; print qq{before substitution(s): '$line' \n}; TUPLE: for my $ar_tuple (@baza_tek) { my ($new_line, $err) = try_substitution($line, @$ar_tuple); if (defined $new_line) { $line = $new_line; # substitution ok if new line defined print qq{ after s/// try: '$line' \n}; } else { # undefined new line: must be an error print qq{$err \n}; } } # end for TUPLE loop print qq{after substitution(s): '$line' \n}; print qq{------------ \n\n}; } # end while LINE loop # subroutines ###################################################### sub try_substitution { my ($string, # string: substitution target $search, # string: search regex $replace, # string: replacement template ) = @_; my (@caps, # all capture groups that might reasonably be used $cap_max, # number of highest capture group actually used $match, # substitution regex match sub-string ); eval { # escalate specific warning to exception-throwing error. use warnings FATAL => 'uninitialized'; $string =~ s{$search}{ # replacement code not entered if search regex throws error. # capture needed dynamic regex variables to external scope. # all capture groups that might possibly appear. @caps = # 0th element is padding (no capture group 0) (undef, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12); # limit capture list to actual capture groups. $#caps = $#-; # max capture group number (0 if none). $cap_max = $#-; $match = ${^MATCH}; qq{qq{$replace}}; }geep; }; # no warnings or any errors in substitution. return $string unless $@; # prepare captured info for 'warning' return. chomp $@; $_ = defined() ? qq{'$_'} : 'undef' for @caps, $match; $cap_max //= 0; # could be undef if search regex threw error # substitution generated warning/exception or an error. return undef, # no successful string substitution join '', qq{ - warning: '$@' \n}, qq{ - for: $search => '$replace' \n}, qq{ - against: $match \n}, ' - ', $cap_max ? qq{$cap_max valid capture(s):} : 'no captures', map sprintf(q{ $%s %s}, $_, $caps[$_]), 1 .. $cap_max ; } # end sub try_substitution() __DATA__ all bad ip6 and zero and zot5 and foo4x thud both ok iipp7 here and iipp8 too and foo42x also bad zot5 thing bad zero here some bad iipp3 and ip4 and foo22x and zot9 and udp2 so-so ok udp7 substitution all ok udp5 and iipp4 and foo98x yea nothing to see here, move along