我有一个需要在多个服务器上运行的脚本,但是,每个服务器可能没有相同版本的Perl可用,并且可能具有不同的功能。
Perl v5.14引入了/r modifier for regular expressions,它返回替换结果并单独保留原始文本。如果没有,我想改用一些后备代码。
以下是一个例子:
#!/usr/bin/perl
# Don't use cryptic variable names
use English;
my $str = "Hello, World!";
my $search = ',';
if ($PERL_VERSION ge v5.14) {
print "Using version that supports /r modifier\n";
# Perl v5.14 introduced the /r flag for regular expressions
# From the perldoc: r - perform non-destructive substitution and return the new value
print "After replacement: " . ($str =~ s/\Q${search}\E/_/gr) . $/;
print "Original string: " . $str . $/;
} else {
print "This version does not support the /r modifier\n";
# Prior to Perl v5.14, no /r option existed and the original string will be clobbered
# To deal with this, we need to make a copy first, then modify the copy instead
my $str_copy = $str;
$str_copy =~ s/\Q${search}\E/_/g;
print "After replacement: " . $str_copy . $/;
print "Original string: " . $str . $/;
}
当Perl v5.14可用时,运行脚本会得到所需的结果:
$ ./version_dependent.pl
Using version that supports /r modifier
After replacement: Hello_ World!
Original string: Hello, World!
当使用小于v5.14的版本时,由于r
我收到语法错误:
$ ./version_dependent.pl
Bareword found where operator expected at ./version_dependent.pl line 15, near "s/\Q${search}\E/_/gr"
syntax error at ./version_dependent.pl line 15, near "s/\Q${search}\E/_/gr"
Execution of ./version_dependent.pl aborted due to compilation errors.
我想得到的是:
$ ./version_dependent.pl
This version does not support the /r modifier
After replacement: Hello_ World!
Original string: Hello, World!
有没有办法让脚本按预期运行?
如果这是一个类C语言,我使用预处理器处理问题,但我不认为Perl具有该功能。
修改:上面的代码只是一个示例 在实际应用中,由于性能原因,我在5.14中使用了一些功能。我可以在小于5.14的版本中手动重新创建功能,但性能会受到影响。
答案 0 :(得分:3)
许多最近的功能都不是向前兼容的。正如您所见,使用对于您运行的perl版本而言过于新的功能,您将获得编译时错误。使用块 - class MissionResource(ModelResource):
text_mission = fields.ToOneField('path.to.TextMissionResource', attribute='text_mission', related_name='mission', full = True, null = True)
class TextMissionResource(ModelResource):
mission = fields.ToOneField(MissionResource, attribute='mission', related_name='text_mission')
将无济于事,因为块的内容需要对当前的perl解释器有效。
您正在检查当前的perl版本和分支。 $]
variable是这样做的一种机制。检查eval
(在$Config{PERL_VERSION}
之后)是另一个。
ThisSuitIsBlack没有向你指出use Config
编译指示,即
if
根据当前perl的功能加载不同的模块。在运行时,条件use if $] >= 5.014, 'Foo::New'; # take advantage of latest syntax,features
use if $] <= 5.014, 'Foo::Old'; # workarounds for missing features
语句可以以相同的方式工作
require
最后,对于依赖于版本的代码,块eval不是一种可行的技术,但字符串eval是。要点是:
if ($] >= 5.014) {
require Foo::New;
} else {
require Foo::Old;
}
See the Test::Builder
module真实地使用这种结构。
答案 1 :(得分:1)
以eval
的字符串形式包装它(因为eval
的块形式会导致同样的错误):
#!/usr/bin/perl
# Don't use cryptic variable names
use English;
my $str = "Hello, World!";
my $search = ',';
if ($PERL_VERSION ge v5.14) {
print "Using version that supports /r modifier\n";
# Perl v5.14 introduced the /r flag for regular expressions
# From the perldoc: r - perform non-destructive substitution and return the new value
eval 'print "After replacement: " . ($str =~ s/\Q${search}\E/_/gr) . $/;';
print "Original string: " . $str . $/;
} else {
print "This version does not support the /r modifier\n";
# Prior to Perl v5.14, no /r option existed and the original string will be clobbered
# To deal with this, we need to make a copy first, then modify the copy instead
my $str_copy = $str;
$str_copy =~ s/\Q${search}\E/_/g;
print "After replacement: " . $str_copy . $/;
print "Original string: " . $str . $/;
}