11

Simple code:

use 5.014;
use warnings;

my $re = <DATA>;
chomp $re;
my $re2 = qr/$re/;
say $re2;
__END__
^\w$

result:

(?^u:^\w$)      #added the (?^u:

Is any correct way to decompile $re2 getting back the original regex?

Motivation: the regex is an config value, so need:

  • read it
  • compile it
  • save it to the file for the later use.

But can't save the compiled regex for the later use, because in every compiling the regex got expanded with the (?^u:, so after several cycles i ended with like:

(?^u:(?^u:(?^u:(?^u:(?^u:^\w$)))))

therefore the question are:

  • is here any correct way, how to save the compiled version?
  • if no way - how to decompile, to getting the original version?
  • any idea?
clt60
  • 62,119
  • 17
  • 107
  • 194
  • You say you read the pattern from a file, so you have what you want to save to a file, so why don't you save it? – ikegami Nov 30 '11 at 20:47

4 Answers4

16

While I would just keep the string copy around for data usage, and then compile a copy when I needed to use it, you can also use the regexp_pattern function from the core re module to return the pattern used to create a compiled regex:

use re 'regexp_pattern';

print regexp_pattern qr/^\w$/;

prints

^\w$
Eric Strom
  • 39,821
  • 2
  • 80
  • 152
  • That's is exactly what i need. Working with perl above 5.10 - so fine... ;) THANX! – clt60 Nov 30 '11 at 19:06
  • That's not what it prints, at least not in 5.14. – ikegami Nov 30 '11 at 20:45
  • @ikegami => I have 5.10.1 here at work, and that is exactly what it prints. Also, it does not fail for `qr/foo\/bar/` it simply returns a value that does not cater to those quoting characters... – Eric Strom Nov 30 '11 at 21:06
  • 1
    From the documentation on [regexp_pattern](http://search.cpan.org/perldoc?re): `In list context it returns a two element list, the first element containing the pattern and the second containing the modifiers used when the pattern was compiled.` When testing, I found that the two examples mentioned above print a list, where the second element is `u`. – TLP Nov 30 '11 at 22:50
4

re::regexp_pattern

Credits to vpit for pointing this out on MagNET #perl.

daxim
  • 39,270
  • 4
  • 65
  • 132
  • Just read than here is another answer for the 'use re ...'. Thanx daxim too - unfortunately can accept only one.. – clt60 Nov 30 '11 at 19:17
3

The original is an operator, not a regex pattern. Only looking at the first value returned by regexp_pattern (the pattern) results in information loss. You also need to look at the second (the flags).

qr/foo/                  # pat: foo  flags: u
qr/foo/u                 # pat: foo  flags: u
use re '/u';  qr/foo/    # pat: foo  flags: u

qr/foo/a                 # pat: foo  flags: a
use re '/a';  qr/foo/    # pat: foo  flags: a

qr/foo/i                 # pat: foo  flags: ui
use re '/i';  qr/foo/    # pat: foo  flags: ui
use re '/a';  qr/foo/i   # pat: foo  flags: ai
use re '/ai'; qr/foo/    # pat: foo  flags: ai

To get the closest possible you can get to the original operator, you want

use re qw( regexp_pattern );
my ($pat, $flags) = regexp_pattern($re);
$pat =~ s{/}{\\/}g;
say qq{qr/$pat/$flags};
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I'm compiling my regexs without flags, so Erics simple version is enough for me. Anyway, Thanks much for the detailed explanation!!! – clt60 Nov 30 '11 at 22:40
  • @jm666, Again, if you know that, why do you need to extract the original pattern from a re? – ikegami Dec 01 '11 at 04:56
0

Perhaps as simple as:

...
($reoriginal = $re2) =~ s{^\(\?.+:(.+)\)}{$1};
say $reoriginal
JRFerguson
  • 7,426
  • 2
  • 32
  • 36