Perl: как получить исходное регулярное выражение из предварительно скомпилированной версии?

Простой код:

use 5.014;
use warnings;

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

результат:

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

Есть ли правильный способ декомпилировать $re2, возвращая исходное регулярное выражение?

Мотивация: регулярное выражение является значением конфигурации, поэтому необходимо:

  • прочитайте его
  • скомпилировать его
  • сохраните его в файле для последующего использования.

Но не может сохранить скомпилированное регулярное выражение для последующего использования, потому что в каждом компиляторе регулярное выражение расширяется с помощью (? ^ u:, поэтому после нескольких циклов я заканчивал так:

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

поэтому вопрос:

  • здесь правильный путь, как сохранить скомпилированную версию?
  • если нет способа - как декомпилировать, получить исходную версию?
  • любая идея?

Ответ 1

В то время как я бы просто сохранил строку для использования данных, а затем скомпилировал копию, когда мне нужно было ее использовать, вы также можете использовать функцию regexp_pattern из ядро re, чтобы вернуть шаблон, используемый для создания скомпилированного регулярного выражения:

use re 'regexp_pattern';

print regexp_pattern qr/^\w$/;

печатает

^\w$

Ответ 3

Оригинал - это оператор, а не шаблон регулярного выражения. Только просмотр первого значения, возвращаемого regexp_pattern (шаблон), приводит к потере информации. Вам также нужно посмотреть на второй (флаги).

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

Чтобы получить максимально возможный доступ, вы можете перейти к исходному оператору, вы хотите

use re qw( regexp_pattern );
my ($pat, $flags) = regexp_pattern($re);
$pat =~ s{/}{\\/}g;
say qq{qr/$pat/$flags};

Ответ 4

Возможно, это просто:

...
($reoriginal = $re2) =~ s{^\(\?.+:(.+)\)}{$1};
say $reoriginal