Двойная интерполяция регулярных выражений в Perl
у меня есть программа Perl, которая хранит регулярные выражения в файлах конфигурации. Они в форме:
regex = ^/d+$
в другом месте регулярное выражение анализируется из файла и сохраняется в переменной - $regex
.
Затем я использую переменную при проверке регулярного выражения, например
$lValid = ($valuetocheck =~ /$regex/);
Я хочу иметь возможность включать переменные perl в конфигурационный файл, например
regex = ^d+$stored_regex$
но я не могу понять, как это сделать.
когда регулярные выражения анализируются Perl их интерпретируют дважды. Сначала переменные расширяются, а затем анализируется само регулярное выражение.
что мне нужно-это три этапа:
Первая интерполяция $regex
, затем интерполируйте переменные, которые он содержит, а затем проанализируйте полученное регулярное выражение.
Обе первые две интерполяции должны быть"регулярными выражениями". например, они должны знать, что строка содержит $
как анкер etc...
какие идеи?
4 ответов
С помощью eval могу помочь вам здесь. Взгляните на следующий код, который он может предварительно скомпилировать регулярное выражение, готовое к использованию:
my $compiled_regexp;
my $regexp = '^\d+$stored_regexp$';
my $stored_regexp = 'a';
eval "$compiled_regexp = qr/$regexp/;";
print "$compiled_regexp\n";
оператор qr/ / может использоваться для предварительной компиляции регулярного выражения. Он позволяет создавать его, но пока не выполняет. Вы можете сначала построить свои регулярные выражения с ним, а затем использовать их.
вы можете определить регулярное выражение в файле конфигурации следующим образом:
regex = ^\d+(??{$stored_regex})$
но вам нужно будет отключить проверку безопасности в блоке, где вы используете regexp, сделав это в своей программе Perl:
use re 'eval';
ваши переменные Perl не находятся в пределах вашего файла конфигурации, и я думаю, что это хорошо. eval-это страшно.
вам было бы лучше реализовать свой собственный шаблон.
Итак, в конфигурационном файле:
regex = ^\d+__TEMPLATE_FIELD__$
в файле config читателя:
# something like this for every template field you need
$regex =~ s/__TEMPLATE_FIELD__/$stored_regex/g;
при использовании:
$lValid = ($valuetocheck =~ m/$regex/)
переместите их в зависимости от того, в какой момент Вы хотите применить замену шаблона.
тангенциально связанный gotcha: если вы делаете двойную интерполяцию inline, и у вас также есть строки подстановки в переменных, рассмотрим:
# the concat with doublequotes in the replacement string
# are to make them PART OF THE STRING, NOT THE STRING DELIMITERS,
# in other words, so the 2nd interpolation sees a double quoted string :
# eval eval $replace -> eval hello world -> syntax error
# eval eval $replace -> eval " hellow world" -> works ok
# see: http://www.perlmonks.org?node_id=687031
if($line =~ s/$search/'"' . $replace . '"'/ee) {
# STUFF...
}