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$
Ответ 2
re::regexp_pattern
Кредиты vpit для указания этого на MagNET #perl.
Ответ 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