不要问为什么,但......
我有一个正则表达式,如果在Windows上运行需要不区分大小写,但在* nix上运行时区分大小写。
以下是我目前正在做的事情的一个示例摘录。
sub relative_path
{
my ($root, $path) = @_;
if ($os eq "windows")
{
# case insensitive with regex option 'i'
if ($path !~ /^\Q$root\E[\\\/](.*)$/i)
{
print "\tFAIL:$root not in $path\n";
}
else
{
return $1;
}
}
else
{
# case sensitive
if ($path !~ /^\Q$root\E[\\\/](.*)$/)
{
print "\tFAIL:$root not in $path\n";
}
else
{
return $1;
}
}
return "";
}
哎呀!重复会伤害我的强迫症,但我的perl-fu很弱。不知怎的,我想让正则表达式选项'i'用于不区分大小写的条件,但我现在不怎么样?
答案 0 :(得分:9)
您可以使用扩展构造来指定选项。例如:
#!/usr/bin/env perl
use warnings; use strict;
my $s = 'S';
print check($s, 'i'), "\n";
print check($s, '-i'), "\n";
sub check {
my ($s, $opt) = @_;
return "Matched" if $s =~ /(?$opt)^s\z/;
return "Did not match";
}
请参阅perldoc perlre。
答案 1 :(得分:5)
您可以使用qr
运算符创建模式并将其存储在标量中:
sub relative_path
{
my ($root, $path) = @_;
my $pattern = ($os eq "windows") ? qr/^\Q$root\E[\\\/](.*)$/i : qr/^\Q$root\E[\\\/](.*)$/;
if ($path !~ $pattern)
{
print "\tFAIL:$root not in $path\n";
}
else
{
return $1;
}
}
这可能不是100%完美,但希望你能得到这个想法。
请务必查看"Quote and Quote-Like Operators" in perlop部分。
编辑:好的,这是一个干燥的解决方案,因为人们在抱怨它。
sub relative_path
{
my ($root, $path) = @_;
my $base_pattern = qr/^\Q$root\E[\\\/](.*)$/;
my $pattern = ($os eq "windows") ? qr/$base_pattern/i : $base_pattern;
if ($path !~ $pattern)
{
print "\tFAIL:$root not in $path\n";
}
else
{
return $1;
}
}
答案 2 :(得分:4)
除了实现既定目标外,这还可以正确处理卷,而不像以前发布的正则表达式模式。
use Path::Class qw( dir );
sub relative_path {
my ($root, $path) = @_;
if ($^O =~ /Win32/) {
require Win32;
$root = Win32::GetLongPathName($root);
$path = Win32::GetLongPathName($path);
}
$root = dir($root);
$path = dir($path);
if ($root->subsumes($path)) {
return $path->relative($root);
} else {
print "\tFAIL:$root not in $path\n";
return "";
}
}
顺便说一句,在那里处理错误并不合适。该函数应该返回一个错误信号(返回undef,抛出异常等),调用者应该按照它认为合适的方式处理它。关注点分离。
答案 3 :(得分:1)
您也可以使用局部修饰符(perl扩展正则表达式选项)来执行此操作:
sub relative_path
{
my ($root, $path) = @_;
my $pattern = "^\Q$root\E[\\\/](.*)$";
$pattern = "(?i)$pattern" if ($os eq "windows");
if ($path =~ /$pattern/)
{
return $1;
}
else
{
print "\tFAIL:$root not in $path\n";
}
}
(在我输入我的答案后,我看到思南也提出了这个建议,但我也决定发布我的答案,因为它给出了一个更具体的答案)