4

In Perl:

my $string = "This is a test";
say "String matches" if $string =~ /this is a test/;          # Doesn't print
say "String sort of matches" if string =~ /this is a test/i;  # Prints

Adding the i flag onto the end of the RE match causes the match to ignore case.

I have a program where I specify the regular expression to match in a separate data file. This works fine. However, I'd like to be able to expand that and be able to specify the regular expression flags to use when checking for a match.

However, in Perl, those RE flags cannot be in a scalar:

my $re_flags = "i";
my $string = "This is a test";
say "This sort of matches" if $string =~ /this is a test/$re_flags;

This results in:

Scalar found where operator expected at ,,, line ,,, near "/this is a test/$re_flags"  
(Missing operator before $re_flags?)
syntax error at ... line ..., near "/this is a test/$re_flags"
Execution of ... aborted due to compilation errors.

Is there a way to use RE flags stored in a scalar variable when evaluating a regular expression?

I know I can use eval:

eval qq(say "This worked!" if \$string =~ /this is a test/$re_flags;);

But I'd like a better way of doing this.

David W.
  • 105,218
  • 39
  • 216
  • 337
  • possible duplicate of [How do I use a variable as a regex modifier in perl?](http://stackoverflow.com/questions/27576498/how-do-i-use-a-variable-as-a-regex-modifier-in-perl) – ThisSuitIsBlackNot May 15 '15 at 18:53
  • 1
    @ThisSuitIsBlackNot, You suggested an answer that's a duplicate itself – ikegami May 15 '15 at 18:56
  • @ikegami I picked that one because I think it (both the question and answers) matches this question better than the post it's [purportedly] a duplicate of. There's nothing wrong with chains of duplicates, as far as I know. – ThisSuitIsBlackNot May 15 '15 at 19:01
  • The answer ikegami gave is much better anyway. I wanted to avoid the whole `eval` and if matching. – David W. May 15 '15 at 19:02
  • @DavidW. Only the last answer in the post I linked uses `eval`, and that answer was downvoted to -2. The other three answers all show the same syntax ikegami used, although I agree that ikegami's answer is better. – ThisSuitIsBlackNot May 15 '15 at 19:06
  • You mean aside that it causes confusion and that it indicates that the previously flagged question isn't actually a duplicate? I suppose. – ikegami May 15 '15 at 19:08
  • @ikegami I agree, the question I linked to is not actually a duplicate and should never have been closed as such. Perhaps it should be reopened and closed as a duplicate of *this* question, which has a much more thorough answer. – ThisSuitIsBlackNot May 15 '15 at 19:35

1 Answers1

9
$ perl -E'say for qr/foo/, qr/foo/i'
(?^u:foo)
(?^ui:foo)

This just goes to show that

/foo/i
s/foo/bar/i

can also be written as

/(?i:foo)/
s/(?i:foo)/bar/

so you could use

/(?$re_flags:foo)/
s/(?$re_flags:foo)/bar/

This will only work for flags that pertain to the regular expression (a, d, i, l, m, p, s, u, x) rather than flags that pertain to the match operator (c, g, o) or the substitution operator (c, e, g, o, r).

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    Something new I learned. I never knew about this, but it's there in `perlre` and actually goes as far back as version 5.8.9: _Any of these modifiers may also be embedded within the regular expression itself using the (?...) construct_ Thanks. – David W. May 15 '15 at 18:59