Двойная интерполяция регулярных выражений в 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... 
}