I need to pass a regex substitution as a variable:
sub proc { my $pattern = shift; my $txt = "foo baz"; $txt =~ $pattern; } my $pattern = 's/foo/bar/'; proc($pattern);
This, of course, doesn't work. I tried eval'ing the substitution:
eval("$txt =~ $pattern;");
but that didn't work either. What horribly obvious thing am I missing here?
Substitutions are language elements that are recognized only within replacement patterns. They use a regular expression pattern to define all or part of the text that is to replace matched text in the input string. The replacement pattern can consist of one or more substitutions along with literal characters.
The Special Character Classes in Perl are as follows: Digit \d[0-9]: The \d is used to match any digit character and its equivalent to [0-9]. In the regex /\d/ will match a single digit. The \d is standardized to “digit”.
Look it up on a text on Perl. Use parentheses. The ( =~ ) operator takes two arguments: a string on the left and a regular expression pattern on the right. Instead of searching in the string contained in the default variable, $_ , the search is performed in the string specified.
Performing a regex search-and-replace is just as easy: $string =~ s/regex/replacement/g; I added a “g” after the last forward slash. The “g” stands for “global”, which tells Perl to replace all matches, and not just the first one.
I need to pass a regex substitution as a variable
Do you? Why not pass a code reference? Example:
sub modify { my($text, $code) = @_; $code->($text); return $text; } my $new_text = modify('foo baz', sub { $_[0] =~ s/foo/bar/ });
In general, when you want to pass "something that does something" to a subroutine ("a regex substitution" in the case of your question) the answer is to pass a reference to a piece of code. Higher Order Perl is a good book on the topic.
sub proc { my($match, $subst) = @_; my $txt = "foo baz"; $txt =~ s/$match/$subst/; print "$txt\n"; } my $matcher = qr/foo/; my $sub_str = "bar"; proc($matcher, $sub_str);
This rather directly answers your question. You can do more - but when I used a qr// term instead of the $sub_str as a simple literal, then the expanded regex was substituted.
I recently needed to create a parser (test parser) for statements with some peculiar (dialect of) SQL types, recognizing lines such as this, splitting it into three type names:
input: datetime year to second,decimal(16,6), integer
The script I used to demo this used quoted regexes.
#!/bin/perl -w use strict; while (<>) { chomp; print "Read: <$_>\n"; my($r1) = qr%^input\s*:\s*%i; if ($_ =~ $r1) { print "Found input:\n"; s%$r1%%; print "Residue: <$_>\n"; my($r3) = qr%(?:year|month|day|hour|minute|second|fraction(?:\([1-5]\))?)%; my($r2) = qr% (?:\s*,?\s*)? # Commas and spaces ( (?:money|numeric|decimal)(?:\(\d+(?:,\d+)?\))? | int(?:eger)? | smallint | datetime\s+$r3\s+to\s+$r3 ) %ix; while ($_ =~ m/$r2/) { print "Got type: <$1>\n"; s/$r2//; } print "Residue 2: <$_>\n"; } else { print "No match:\n"; } print "Next?\n"; }
We can argue about the use of names like $r1, etc. But it did the job...it was not, and is not, production code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With