我试图在评估中使用Perl的正则表达式替换来帮助使一些配置文件在Clearcase期间更具动态性 - > Git迁移。 Clearcase系统高度依赖于/ vob /目录,但是我们需要让它更加动态,让我们的Jenkins构建变得快乐。我试图降低在迁移过程中打破Clearcase构建的可能性。
我有一个配置文件是一个文本文件,每行有一个路径:
/vob/config/file1
/vob/config/file2
/vob/config/file3
此配置会对这些配置文件执行一些其他操作。编排那些"东西"由Perl脚本管理。我希望在运行脚本时可以覆盖一些环境变量(" VOB_FOO")。
我是Perl的新手,所以我认为使用Perl环境变量语法,对它进行正则表达式并在我处理文件时在线评估替换结果。< / p>
我希望我的新配置文件在文件中包含明确的$ ENV {&#39; VOB_FOO&#39;}条目,因此文件将变为:
$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";
}
}
我也愿意接受批评或提出更好的方法来做到这一点 - 在我努力实现这一目标的过程中,我并没有依赖这种方法或代码。
答案 0 :(得分:2)
我认为你需要的就是这个。它不是提取整个表达式,而是采用哈希键并在真实%ENV
我添加了一个替换,以便可以使用或不使用引号来编写散列键,并且可能具有前导或尾随空格
$second =~ s/\$ENV\{\s*(?|(\w+)|'(\w+)')\s*\}/$ENV{$1}/g
答案 1 :(得分:0)
Since you are capturing a literal string the $1
contains mere characters ('$'.'E'.'N'...
), which first need be interpolated into a variable, which can then be evaluated. So, need two 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
}
Since }
isn't ever a part of the environment variable name I simply match everything up to }
using the non-greedy .*?
. See this post for a detailed explanation of ee
.
However, note that ee
comes with serious security considerations, as it will turn the given string into a variable† and eval it, no questions asked. It also doesn't work in taint mode. So use carefully and only in tightly controlled circumstances.
A safer way is to capture the environment variable name itself and then normally have %ENV
of it evaluated in the replacement, as Borodin's answer suggests
$second =~ s/\$ENV(\{(.*?)\}/$ENV{$1}/g;
Either way, also note that you don't need to first match then substitute.
† The danger is really that the string may happen to contain any code, which is blindly eval
-ed.