Двойная интерполяция регулярных выражений в Perl - PullRequest
7 голосов
/ 09 февраля 2009

У меня есть программа Perl, которая хранит регулярные выражения в файлах конфигурации. Они в форме:

regex = ^/d+$

В другом месте регулярное выражение анализируется из файла и сохраняется в переменной - $regex. Затем я использую переменную при проверке регулярных выражений, например,

$lValid = ($valuetocheck =~ /$regex/);

Я хочу иметь возможность включать переменные perl в файл конфигурации, например,

regex = ^\d+$stored_regex$

Но я не могу понять, как это сделать.

Когда регулярные выражения анализируются Perl, они интерпретируются дважды. Сначала раскрываются переменные, а затем разбирается само регулярное выражение.

Мне нужен трехэтапный процесс: Сначала интерполируйте $regex, затем интерполируйте содержащиеся в нем переменные и затем анализируйте полученное регулярное выражение. Обе первые две интерполяции должны быть «осведомлены о регулярном выражении». например они должны знать, что строка содержит $ в качестве якоря и т. д. *

Есть идеи?

Ответы [ 4 ]

7 голосов
/ 09 февраля 2009

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

regex = ^\d+(??{$stored_regex})$

Но вам нужно будет отключить проверку безопасности в блоке, где вы используете регулярное выражение, выполнив это в вашей Perl-программе:

use re 'eval';
3 голосов
/ 09 февраля 2009

Ваши переменные Perl не входят в область действия вашего файла конфигурации, и я думаю, что это хорошо. Эвал страшен.

Вам бы лучше реализовать свои собственные шаблоны.

Так в конфигурационном файле:

regex = ^\d+__TEMPLATE_FIELD__$

В программе чтения конфигурационных файлов:

# something like this for every template field you need
$regex =~ s/__TEMPLATE_FIELD__/$stored_regex/g;

При использовании:

$lValid = ($valuetocheck =~ m/$regex/)

Перемещайте их в зависимости от того, в какой момент вы хотите применить замену шаблона.

3 голосов
/ 09 февраля 2009

Использование eval может помочь вам здесь. Взгляните на следующий код, он может предварительно скомпилировать регулярное выражение, готовое для использования последним:

my $compiled_regexp;
my $regexp = '^\d+$stored_regexp$';
my $stored_regexp = 'a';

eval "\$compiled_regexp = qr/$regexp/;";
print "$compiled_regexp\n";

Оператор qr // может использоваться для предварительной компиляции регулярного выражения. Он позволяет вам его построить, но пока не выполняет. Вы можете сначала построить свои регулярные выражения с ним и затем использовать их позже.

0 голосов
/ 10 апреля 2010

Тангенциально связанный гоча: если вы выполняете двойную интерполяцию 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 $1 hello world -> syntax error 
#     eval eval $replace -> eval "$1 hellow world"  -> works ok 
# see: http://www.perlmonks.org?node_id=687031  

if($line =~ s/$search/'"' . $replace . '"'/ee) {
     # STUFF... 
}
...