Подстановка в Perl Regex, оценка переменных среды - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь использовать Perl для подстановки регулярных выражений с оценкой, чтобы помочь сделать некоторые файлы конфигурации более динамичными во время переноса Clearcase -> Git.Система Clearcase сильно зависит от каталога / vob /, но нам нужно сделать это более динамичным, чтобы наши сборки Jenkins были довольны.Я пытаюсь уменьшить вероятность того, что я нарушу сборки Clearcase во время миграции.

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

/vob/config/file1
/vob/config/file2
/vob/config/file3

Эта конфигурация выполняет некоторые дополнительные действия с этими файлами конфигурации.Управление этими «вещами» управляется скриптом Perl.Я хотел бы иметь несколько переменных среды ("VOB_FOO"), которые я могу переопределить при запуске сценария.

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

Я хочу, чтобы в моем новом файле конфигурации были явные записи $ ENV {'VOB_FOO'} в файле,таким образом, файл станет:

$ENV{'VOB_FOO'}/config/file1   ->    /home/me/foo/config/file1
$ENV{'VOB_FOO'}/config/file2   ->    /home/me/foo/config/file2
$ENV{'VOB_FOO'}/config/file3   ->    /home/me/foo/config/file3

И полученная подстановка регулярного выражения + оценка превратится в (если VOB_FOO = / home / me / foo):

$ENV{'VOB_FOO'}/config/file1   ->    /home/me/foo/config/file1
$ENV{'VOB_FOO'}/config/file2   ->    /home/me/foo/config/file2
$ENV{'VOB_FOO'}/config/file3   ->    /home/me/foo/config/file3

Мое регулярное выражениесоответствует отлично, и кажется, что замена работает, но оценка части замены нет, и я мог бы использовать некоторую помощь здесь.Я получаю успешное совпадение, но подстановка звучит так:

$ENV{'VOB_FOO'}/config/file1   ->    $ENV('VOB_FOO'}/config/file1
$ENV{'VOB_FOO'}/config/file2   ->    $ENV('VOB_FOO'}/config/file2
$ENV{'VOB_FOO'}/config/file3   ->    $ENV('VOB_FOO'}/config/file3

Есть ли какие-либо предостережения относительно этой оценки или каким-то образом я могу сделать эту работу правильно?Вот мой код:

## See if we need to substitute an environment variable (e.g., is there a $ENV{} anywhere?)
## s - substitute through regular expressions (s/foo/bar/e)
## e modifier evaluates replacement as perl statement

{
    use re 'debugcolor';

    # this is for debugging only - I want to substitute 
    # grab the $ENV('VOB') string from the file and substitute
    # I may have multiple environment variables that I have to 
    # contend with. 
    my $vob = $ENV{'VOB'};  
    print $vob; 
    print "\n";

    my $regexp = qr/(\$ENV\{[\'][\w]*[\']\})/;

    if( $second =~ m/$regexp/ )
    {
        print "Found the regexp; attempting substitution.\n";
        $second =~ s/$regexp/$1/e;  
    }
    else
    {
        print $regexp + "\n";
        print $second + "\n";
        print "Did not find the regexp\n";
    }
}

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

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Поскольку вы захватываете литеральную строку, $1 содержит простые символы ('$'.'E'.'N'...), которые сначала необходимо интерполировать в переменную, которая затем может быть оценена.Итак, нужно два evals

use warnings;
use strict;
use feature 'say';

my $var = q(a_$ENV{SHELL}_b);   # like $ENV{'VOB'} read from a file

if ( $var =~ s/(\$ENV\{.*?\})/$1/ee ) {
    say $var
}

Поскольку } никогда не является частью имени переменной среды, я просто сопоставляю все до }, используя не жадный .*?.См. этот пост для подробного объяснения ee.

Однако обратите внимание, что ee имеет серьезные соображения безопасности, так как превращает данную строку в переменную и eval это, без вопросов.Это также не работает в грязном режиме.Поэтому используйте осторожно и только в строго контролируемых условиях.

Более безопасный способ - захватить само имя переменной среды, а затем, как правило, %ENV ее оценивать при замене, как ответ Бородина предлагает

$second =~ s/\$ENV(\{(.*?)\}/$ENV{$1}/g;

В любом случае, также обратите внимание, что вам не нужно сначала сопоставлять, а затем заменять.


В действительности существует опасность, что строкаможет случиться так, что он содержит любой код , который слепо eval -ed.

0 голосов
/ 04 июня 2018

Я думаю, все, что вам нужно, это.Вместо того, чтобы извлекать все выражение целиком, он берет ключ хеша и использует его на действительном %ENV

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

$second =~ s/\$ENV\{\s*(?|(\w+)|'(\w+)')\s*\}/$ENV{$1}/g
...