Perl 正则表达式替换,环境变量的评估



我正在尝试使用 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 regexpn";
}
}

我也愿意就更好的方法提出批评或建议 - 当我努力实现这一目标时,我不受这种方法或代码的束缚。

我认为你所需要的只是这个。它不是提取整个表达式,而是获取哈希键并将其用于实际%ENV

我添加了一个交替,以便哈希键可以写成带引号或不带引号,并且可以有前导或尾随空格

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

捕获文字字符串后,$1只有字符('$'.'E'.'N'...(,首先需要将其制成变量名,然后进行评估。所以,需要两个评估

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 ) {  # WARNING: security?
say $var
}

由于}从来都不是环境变量名称的一部分,因此我只是使用非贪婪.*?将所有内容与}匹配。有关ee的详细说明,请参阅此帖子。

但是,请注意,ee带有严重的安全考虑,因为它会将给定的字符串转换为变量并对其进行评估,没有任何问题。它在污点模式下也不起作用。 因此,请谨慎使用,并且只能在严格控制的情况下使用。

一种更安全的方法是捕获环境变量名称本身,然后通常在替换中评估其中%ENV,正如 Borodin 的答案所建议的那样

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

无论哪种方式,还要注意,您不需要先匹配然后替换。


危险在于,如果字符串碰巧包含任何代码,则会盲目eval-ed

最新更新