2013-05-11 109 views
1

我想知道是否有一種優雅的方法來匹配一個預編譯的正則表達式與另一個正則表達式?我想不是,但仍然決定問。在Perl中匹配正則表達式和另一個正則表達式

說,我想找到對應於特定模式的Puppet的node.pp中的所有節點。問題是,節點名稱可以(並且通常)被定義爲正則表達式本身。例如,可能需要查找'生產'環境中的所有節點,這些節點都按照慣例以'p'開頭,然後是1或2 /^p[12].+$/。換句話說,

p(1|2)proxy-[1-4].domain.lan 
p1smtp-[1-2].domain.lan 
p[12]what-not-[1-8].domain.lan 

應該匹配,而

q(1|2)proxy-[1-4].domain.lan 
q(1|2)smtp-[1-2].domain.lan 
q(1|2)what-not-[1-8].domain.lan 

不應該。

目標字符串(如果編譯爲正則表達式)都是更一般表達式的子情況。所以我想知道,如果有任何捷徑?

當然,可以將節點名稱作爲包括所有'正則表達式'變體的文字字符串 - 在該特定情況下不應該很難。

+0

那麼,你想與哪個正則表達式進行比較?你是說你想檢查是否匹配,比如'p(1 | 2)proxy- [1-4] .domain.lan'也匹配'^ p [12]。+ $'?這些正則表達式來自哪裏?特別是第二套。 – Borodin 2013-05-11 14:24:03

+0

@Borodin:我需要一個(更一般的)正則表達式來匹配其他更具體的類正則表達式字符串。如果類似於正則表達式的字符串可能以某種方式被解釋爲正則表達式而不是字符串,那將會更容易。該示例取自Puppet的node.pp文件。現在回答這個問題,見下文。 – badbishop 2013-05-11 17:18:39

回答

4

「如果你能想起來,有一個爲一個CPAN模塊」。它就像Perl的規則34一樣。

所以實際上有Regexp::Compare給定兩個正則表達式字符串可以(有時)決定一個正則表達式是否匹配另一個正則表達式的真正子集。請注意,爲了確保這一點,我在開始時固定了輸入正則表達式。那麼is_less_or_equal將返回true,如果$metarx可以匹配$rx匹配的所有字符串。

use strict; use warnings; use 5.010; 
use Regexp::Compare qw(is_less_or_equal); 

my @rx = (
    'p(1|2)proxy-[1-4].domain.lan', 
    'p1smtp-[1-2].domain.lan', 
    'p[12]what-not-[1-8].domain.lan', 
    'q(1|2)proxy-[1-4].domain.lan', 
    'q(1|2)smtp-[1-2].domain.lan', 
    'q(1|2)what-not-[1-8].domain.lan', 
); 
my $metarx = '^p[12]'; 

for my $rx (@rx) { 
    say "/$metarx/ ≥ /^$rx/ ?\t", is_less_or_equal("^$rx", $metarx) ? "yes" : "no"; 
} 

輸出:

/^p[12]/ ≥ /^p(1|2)proxy-[1-4].domain.lan/ ? yes 
/^p[12]/ ≥ /^p1smtp-[1-2].domain.lan/ ?   yes 
/^p[12]/ ≥ /^p[12]what-not-[1-8].domain.lan/ ? yes 
/^p[12]/ ≥ /^q(1|2)proxy-[1-4].domain.lan/ ? no 
/^p[12]/ ≥ /^q(1|2)smtp-[1-2].domain.lan/ ?  no 
/^p[12]/ ≥ /^q(1|2)what-not-[1-8].domain.lan/ ? no 

我相信這確實你腦子裏的東西。 (注意:不要使用正則表達式對象,但只是普通的字符串 - 這個模塊可能在一些字符串處理時遇到困難)

+0

是的,謝謝你,這正是我所想到的。那麼,我的第一個想法是一些內置功能,但如果一個CPAN模塊能夠工作 - 對我來說很好! – badbishop 2013-05-11 17:12:47