Add "m" modifier to qr pattern passed as parameter
The problem is that you need to change a qr
-ed expression, which is a regex object which
...magically differs from a string containing the same characters:
ref(qr/x/)
returns "Regexp"; however, dereferencing it is not well defined...
I can't find a way to change it, or add a flag to it (other than to edit its stringification).
However, if you can change the approach so to define (non-qr
) variables to start with and then later qr
-them as needed then it works as desired
use strict;
use warnings;
use v5.16.3;
use Test::More tests => 3;
my $no_m_modifier_re = q{^line1\n^line2}; # not qr{} but q{}; just a string
my $text = <<'EoM';
line1
line2
line3
EoM
unlike( $text, qr{$no_m_modifier_re}, 'Text does not match ^ equivalent to \A' );
like( $text, qr{$no_m_modifier_re}m, 'Text matches with the modifier' );
like( $text, qr{(?m)$no_m_modifier_re}, 'Text matches with the modifier' );
Along with strings one can set up qr
-ed variables as well, for convenience,† but the main idea is that the user forms a regex pattern along with needed fine-tuning, for example by modifiers.
† If either may get passed around they can be told apart by ref
I tried
qr{(?^m:$no_m_modifier_re)}
like you suggested, but it still fails. The test reportsdoesn't match '(?^u:(?^m:(?^u:^line1\n^line2)))'
You are trying to modify a compiled pattern. For that, you need the following:
use re qw( is_regexp regexp_pattern );
my $re = qr/^line1\n^line2/;
my ($pat, $mods) =
is_regexp($re)
? regexp_pattern($re)
: ( $re, "" );
$mods .= 'm' if $mods !~ /m/;
$re = eval("qr/\$pat/$mods")
or die($@); # Should never happen.
It also works with uncompiled patterns, resulting in a compiled pattern with minimal (?:)
nesting.
The result for "abc" is qr/abc/m which stringifies as (?^um:abc)
The result for qr/abc/ is qr/abc/m which stringifies as (?^um:abc)
The result for qr/abc/m is qr/abc/m which stringifies as (?^um:abc)
The result for qr/abc/s is qr/abc/sm which stringifies as (?^ums:abc)
The result for qr/abc/sm is qr/abc/sm which stringifies as (?^ums:abc)
You're almost there. In Perl 5.16.3, it's
qr/(?^m:pattern)/ # equiv to /pattern/m
In earlier versions, it would be something like
qr/(?m-xis:pattern)/ # equiv to /pattern/m
qr/(?ix-ms:patterm)/ # equiv to /pattern/ix
This won't work for all regexp modifiers. In particular, the /g
modifier can't be emulated this way.
Demo:
$ perl -E 'say 0 + ("CAT" =~ /cat/)'
0
$ perl -E 'say 0 + ("CAT" =~ /(?^i:cat)/)'
1
Update: found the docs here. Too long to excerpt, but they provide a much broader and deeper understanding of "embedded pattern-match modifiers" than my answer.