Perl正则表达式如何否定一部分

时间:2012-02-02 12:38:39

标签: regex perl negate

我必须解散

D= d1| d2|...|dn

F=f1|f2|...|fn

目前我用if语句检查这两个regexp,如下所示:

if (($text_to_search =~ $D) && ($text_to_search !~ $F))

我如何否定F?是否有可能对整个析取或F的每一个析取使用否定的外观?

我应该是这样的:

regexp = (d1)| (d2) | (d3)  ... (dn) | NOT (f1) | NOT (f2) | ... | Not (fn)

括号对于否定模式是必要的,而不仅仅是第一个单个字符,不是吗?

编辑: 例如D是:a|b|c|d,F是:1|2|3

现在行为应该是这样的:

input: "abc" --> accepted
input: "a" --> accepted
input: "abc1" --> Not accepted
input: "2" --> NOT accepted
input: "a2bc1" --> Not accepted
(input: "xyz999" --> does not match - shouldn't be accepted)

F-disjunct应该是“当在输入序列中看到这个不匹配时”

1 个答案:

答案 0 :(得分:2)

是的,您可以使用否定前瞻。使用您的符号我们可以构造这样一个组合正则表达式的形状:

/(?!F)D/

虽然有细微差别。让我们考虑一个简单的例子。

my $patternD = '^(\d\d\d\d | \w\w)$';
my $patternF = 'AA | 12';

如您所见,patternD匹配由4位数或2个字符组成的字符串。 PatternF匹配AA12。因此,以下片段打印出我们期望的内容。

my $str = '1121';
print "patternD matches\n" if $str =~ /$patternD/x; # patternD matches
print "patternF matches\n" if $str =~ /$patternF/x; # patternF matches

现在,让我们使用天真的方法创建一个组合的正则表达式。

my $combined = "(?!($patternF))$patternD";
print "Combined regex matches\n" if $str =~ /$combined/x; # Combined regex matches?!
哎呀,我们这里有误报! (记住,当且仅当正则表达式D匹配而F不匹配时,我们的组合正则表达式才匹配,但事实并非如此)。为什么是这样?答案很简单。我们组合了正则表达式,这样如果D在某个位置匹配,那么F只能匹配相同的位置。在这种情况下,D匹配$str\d\d\d\d替代)的开头,AA12都不匹配。但解决方案很简单。我们应该在它之前添加.*给予F一些灵活性。最终结果是:

 my $combined = "(?!.*($patternF))$patternD";

无论D匹配哪里,F仍然有机会匹配字符串中的任何位置。

这个例子说明你想要实现的目标绝对可行,但你不能简单地将两个正则表达式混合在一起,而是首先要仔细检查最终结果。

HTH