2012-02-02 54 views
3

我不得不分離項Perl的正則表達式如何抵消一部分

D= d1| d2|...|dn 
此刻

F=f1|f2|...|fn 

我檢查這兩個正則表達式使用if語句看起來像這樣:

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

我該如何否定F?是否有可能對整個不相交的情況使用負面查找或F的每一個分歧?

我應該是這樣的:

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

括號是必要的否定模式,不僅是第一個單個字符,arn't他們?

編輯: 例如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-間斷應該像「在看到這個時輸入序列不匹配「

+1

您能告訴我們一些示例輸入和期望的行爲嗎? – Toto 2012-02-02 13:48:51

+0

目前還不清楚你想要什麼。你是否想要像if語句那樣具有相同的功能,但只有一個條件/表達式? – Qtax 2012-02-02 14:19:14

+0

FWIW,這個問題對我來說很明顯,我只是不想回答。 – daxim 2012-02-02 14:49:32

回答

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之前加上.*來給F一些靈活性。最終結果是:

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

無論D匹配在哪裏,F仍然有機會匹配字符串中的任何位置。

這個例子表明你想要達到的是絕對可行的,但是你不能簡單地將你的兩個正則表達式混合在一起,你應該首先仔細檢查最終結果。

HTH

+0

非常感謝你:) – Tyzak 2012-02-02 14:59:29