2013-04-10 36 views
2

我试图匹配/ ezmlm-(任何字,除'杂草'或'返回')\ s + /与正则表达式。下面展示了foreach循环它做正确的事,并试图的正则表达式几乎不:带有负向预测的Perl正则表现出现意外行为

#!/usr/bin/perl 
use strict; 
use warnings; 

my @tests = (
    { msg => "want 'yes', string has ezmlm, but not weed or return", 
     str => q[|/usr/local/bin/ezmlm-reject '<snip>'], 
    }, 
    { msg => "want 'yes', array has ezmlm, but not weed or return", 
     str => [ <DATA> ], 
    }, 
    { msg => "want 'no' , has ezmlm-weed", 
     str => q[|/usr/local/bin/ezmlm-weed '<snip>'], 
    }, 
    { msg => "want 'no' , doesn't have ezmlm-anything", 
     str => q[|/usr/local/bin/else '<snip>'], 
    }, 
    { msg => "want 'no' , ezmlm email pattern", 
     str => q[crazy/but/legal/[email protected]], 
    }, 
); 

print "foreach regex\n"; 
foreach (@tests) { 
    print doit_fe(ref $_->{str} ? @{$_->{str}} : $_->{str}) ? "yes" : "no"; 
    print "\t"; 
    print doit_re(ref $_->{str} ? @{$_->{str}} : $_->{str}) ? "yes" : "no"; 
    print "\t<--- $_->{msg}\n"; 
}; 

# for both of the following subs: 
# @_ will contain one or more lines of data 
# match the pattern /ezmlm-(any word except 'weed' or 'return')\s+/ 

sub doit_fe { 
    my $has_ezmlm = 0; 
    foreach (@_) { 
     next if $_ !~ m/ezmlm-(.*?)\s/; 
     return 0 if $1 eq 'weed' or $1 eq 'return'; 
     $has_ezmlm++; 
    }; 
    return $has_ezmlm; 
}; 

sub doit_re { return grep /ezmlm-(?!weed|return)/, @_; }; 

__DATA__ 
|/usr/local/bin/ezmlm-reject '<snip>' 
|/usr/local/bin/ezmlm-issubn '<snip>' 
|/usr/local/bin/ezmlm-send '<snip>' 
|/usr/local/bin/ezmlm-archive '<snip>' 
|/usr/local/bin/ezmlm-warn '<snip>' 

示例程序的输出如下:

foreach regex 
yes yes <--- want 'yes', string has ezmlm, but not weed or return 
yes yes <--- want 'yes', array has ezmlm, but not weed or return 
no no <--- want 'no' , has ezmlm-weed 
no no <--- want 'no' , doesn't have ezmlm-anything 
no yes <--- want 'no' , ezmlm email pattern 

在过去的情况下,正则表达式失败,匹配一个愚蠢但合法的电子邮件地址。如果我修改的正则表达式,像这样的负先行模式后加一个\ s:

grep /ezmlm-(?!weed|return)\s+/ 

正则表达式不能在所有的匹配。我假设它与消极模式的工作方式有关。我试图使否定不贪心,但似乎有一些教训埋在'perldoc perlre'中,正在逃避我。是否有可能使用一个正则表达式来完成此操作?

+0

这很奇怪。试试:'/ ezmlm - (?!(weed | return))/'。我不确定它会改变什么,但它值得问... – FrankieTheKneeMan 2013-04-10 22:32:59

+0

电子邮件匹配在这里的正则表达式:http://www.online-utility.org/text/grep.jsp – George 2013-04-10 22:43:55

回答

4

负先行是零宽度这意味着如果一个或多个空格字符紧跟"ezmlm-"正则表达式

/ezmlm-(?!weed|return)\s+/ 

将只匹配。

的模式,因为它包含后面没有"weedy""return""ezmlm-"

/ezmlm-(?!weed|return)/ 

将匹配

"crazy/but/legal/[email protected]" 

尝试

/ezmlm-(?!weed|return)\S+\s+/ 

其中\S+是一个或多个非空格字符(或改用[^@\s]+如果你想拒绝的电子邮件地址,即使后面有一个空格)。

+0

所以*这是*零宽度意味着什么。谢谢迈克! – 2013-04-11 19:57:30

相关问题