2012-02-02 155 views
3

请考虑下面的脚本,即使$ b是部分匹配,我也想匹配$ b到$ a。 这可以做到吗?Perl部分匹配

$a="MCF-7"; 
$b="MCF"; 
if($b=~m/$a/i) 
{ 
    print "FOUND"; 
} 
+4

难道你不能扭转这种感觉吗? 'print“FOUND”if $ a =〜/ $ b/i;'? – unpythonic 2012-02-02 03:58:35

回答

8

虽然正则表达式可以做到这一点,这听起来像你的问题也可以与index功能来解决:

say index($haystack, $needle) >= 0 ? 'match' : 'fail'; # any position 
say index($haystack, $needle) == 0 ? 'match' : 'fail'; # anchored at start 

index功能是区分大小写的。如果您希望进行不敏感匹配,请将uclc函数应用于两个参数。

尽管index函数将比正则表达式快得多,但如果您确实需要正则表达式解决方案,则可以构建一个正则表达式生成器,以生成一系列将执行部分匹配的更改。

sub build_partial { 
    my ($str, $min) = (@_, 1); 
    my @re; 
    for (0 .. length($str) - $min) { 
     my $str = substr $str, $_; 
     for ($min .. length $str) { 
      push @re, quotemeta substr $str, 0, $_ 
     } 
    } 
    my $re = join '|' => sort {length $a <=> length $b} @re; 
    qr/^(?:$re)$/i 
} 

my $haystack = 'MCF-7'; 
my $needle = 'MCF'; 

my $regex = build_partial $haystack; 

say $needle =~ /$regex/ ? 'match' : 'fail'; # match 

MCF-7生成的正则表达式如下:

/^(?:M|C|F|7|MC|CF|\-|MCF|F\-|\-7|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i 

而且即使针是从草垛单个字符,将匹配。 build_partial有一个可选的数字,指示匹配所需的最小长度:

my $regex_3 = build_partial $haystack, 3; 

产生此正则表达式:

/^(?:MCF|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i 

这些模式匹配来自任何位置开始的子字符串。如果你想要它锚定在字符串的前面,build_partial变得更简单一点:

sub build_partial { 
    my ($str, $min) = (@_, 1); 

    my $re = join '|' => map { 
     quotemeta substr $str, 0, $_ 
    } $min .. length $str; 

    qr/^(?:$re)$/i 
} 
+0

我喜欢这种方法,但我很好奇你为什么使用'join'|' =>'而不是'join'|' '。 – flesk 2012-02-02 09:37:56

+0

@flesk =>只是个人的编码偏好。我倾向于在任何时候使用胖箭头来描述参数之间的有用关系。所以'join''=> @ list',但不要'push @array => @list',因为这是倒退的 – 2012-02-02 14:03:32

7

你似乎有$a$b混合起来:

use strict; 
use warnings; 
my $a="MCF-7"; 
my $b="MCF"; 
if($a=~/$b/i) #tests for case-insensitive matching of $b within $a. 
{ 
print "Found\n"; 
} 

在你的问题中的代码没有产生输出,因为有内"MCF"没有匹配的"MCF-7"