2012-01-12 66 views
1

我有一個用C#(3.5框架)編寫的ASP.NET應用程序,其中用戶向我提供了我們放置規則的模式列表。我可以編寫代碼來手動說明每種模式,但希望找到一種方法來使用正則表達式(或任何真正的方法)來處理它們,這樣我就可以允許用戶創建更多模式(遵循一些當然的指導)未來。需要正則表達式來匹配用戶生成的模式

我會盡我最大努力展示我正在嘗試做的事情。我非常感謝你的幫助。

這裏有幾個的圖案的:

模式1: 要素1:CxxxxRxxxx 要素2:CxxxxRzzzz 結果:桶1

圖案2: 要素1:CxxxxRxxxx
元件2 :CxxxxRxxxx 結果:桶2

模式3: 要素1:PCxxxxxxxx
要素2:PCzzzzzzzz 結果:鬥3

模式4: 要素1:PCxxxxxxxx
要素2:UxxxxRxxxx 結果:鬥4

這裏是他們的意思,以及如何我需要處理它們。對於初學者來說,所有元素的長度總是10個字符。每個圖案的字母字符都是不變的。 X和Z可以是數字或字母。 X和Z在這種模式中所表達的意思是這兩個元素的其他部分是否相互匹配。例如,我的輸入數據是元素1的「C1234R5678」,元素2的「C1234R9999」。在這種情況下,結果將是「桶1」,因爲它匹配爲此條件定義的模式「C」匹配,但「R」之後的數字不匹配)。

在另一個例子中,我的輸入數據是元素1的「C1234R5678」和元素2的「C1234R5678」。在這種情況下,結果將是「桶2」,因爲它匹配爲這個條件定義的模式在「C」匹配之後,以及「R」匹配之後的數字)。

在另一個例子中,我的輸入數據是元素1爲「PC12345678」,元素2爲「PC87654321」。在這種情況下,結果爲「桶3」,因爲它匹配爲此條件定義的模式之後的「PC」不匹配)。

在最後的例子中,我的輸入數據爲「PC12345678」作爲元件1和「U1234R5678」用於元件2。在這種情況下,結果將是「鬥4」,因爲這(在這個條件定義的模式匹配後4個數字的「PC」匹配在U後的4號和最後4位PC元件的元件2的R後匹配4個位數)。

正如你可以看到,該模式可以是字母或字母后的數字的整體運行之後的某個時候,你正在確定4個數字不同。

謝謝你的時間。

回答

0

你可以這樣做:

For each (Element1,Element2) pair: 
    match Element1,Element2 on "(x+|z+)" -> matches1,matches2 

    for (i=0;i<min(matches1,matches2);i++) { 
     replace 'x+' by '([A-Za-z0-9]{matches1[i].Length})' 
     // note: need the brackets here to act as capturing brackets 
     // so that backreferences can be used! 

     if matches2[i] is 'xxxxx': 
      replace 'x+' by '(?!\i)[A-Za-z0--9]{matches2[i].Length}' 
     else if matches2[i] is 'zzzzz': 
      replace 'z+' by '\i' 
    } 
    Then replace miscellaneous leftover 'xxxx' by '[A-Za-z0-9]{lengthofmatch}'. 

    Then join the new Element1 and Element2 by a delimiter e.g. '-' 

這將構建一個像一堆字符串:

//Pattern 1 
C([A-Za-z0-9]{4})R([A-Za-z0-9]{4})-C(?!\1)[A-Za-z0-9]{4}R\2 
//Pattern 2 
C([A-Za-z0-9]{4})R([A-Za-z0-9]{4})-C(?!\1)[A-Za-z0-9]{4}R(?!\2)[A-Za-z0-9]{4} 
//Pattern 3 
PC([A-Za-z0-9]{8})-PC\1 
//Pattern 4 
PC([A-Za-z0-9]{8})-U(?!\1)[A-Za-z0-9]{4}R[A-Za-z0-9]{4} 

然後,對於每個輸入數據添加由' - '(例如"C1234R5678-C1234R9999")分隔的Element1和Element2,並匹配每個模式,並在第一次匹配時停止。

+0

謝謝你的幫助。我試圖將這些代碼實現到我自己的代碼中。從使用您提供的正則表達式開始。我使用以下代碼: string strRegex = @「PC [A-Za-z0-9] {8} -PC \ 1」; RegexOptions myRegexOptions = RegexOptions。沒有; 正則表達式myRegex = new Regex(strRegex,myRegexOptions); string strTargetString = @「PC12345678-U1234R5678 \ n」; 我收到以下錯誤: 引用未定義的組號碼1. – user295197 2012-01-13 02:35:59

+0

好吧,在弄清楚這個後,我得到了一些調整結果。你們都非常鼓舞人心,並且使得這項工作比我想象的更容易實施。乾杯! – user295197 2012-01-13 04:02:45

+0

哦,道歉,'Element1'中的每個'xxx'組都需要圍繞它來捕獲括號,以便反向引用是可能的!我的壞 - 更新後。 – 2012-01-13 04:05:35

1

一種方法是以連接元件(可能與不能出現在的元素的分離器),所以每一個都可以通過一個單一的正則表達式匹配。使用capturing and backreferences強制稍後的子字符串進行匹配。使用負數lookaheads以確保子字符串與先前字符串不匹配;否則,您必須依賴模式檢查的順序來確保模式匹配正確(在示例中,您必須在第一個數據庫之前檢查數據塊2)。使用squiggly bracket quantifiers來匹配特定數量的字符。

/C(.{4})R\1-C\1R(?!\1).{4}/ -> bucket 1 
/C(.{4})R\1-C\1R\1/   -> bucket 2 
/PC(.{8})-PC(?!\1).{8}/  -> bucket 3 
/PC(.{4})(.{4})-U\1R\2/  -> bucket 4 

代替 「任何」 字符(點),則可以限制部件只是字母數字字符([A-Za-z\d])或標識符字符(\w,相當於 '[A-ZA-Z \ D_]' )。

將映射存儲在列表中,然後在確定要使用哪個存儲桶時遍歷列表。模式和桶之間的其他映射可以附加到列表中。

當然,這將需要您的用戶能夠編寫正則表達式,儘管您可以想出一個更簡單的語言,將其轉換爲正則表達式。例如,您可以讓用戶指定「{n}」和「\ k」,其中前者意味着匹配不應與任何前一組匹配的許多字符,而後者意味着匹配「{n }」。要翻譯爲正則表達式,用「(。{n})」(或「(\ w {n})」)替換每個「{n}」,在k = 1前加上「(?!\ k)」到n -1。使用排序的-C#,更換可能會被指定爲:

(1..n-1).sum(k => "(?!\\" + k + ")") + "(\\w{"+n+"})" 
+0

我曾嘗試在代碼中使用其中一些應該是真的,另一個是假的。現在我只對兩個人都是虛假的。 string regEx = @「/ C(。{4})R \ 1-C \ 1R(?!\ 1)。{4} /」; string testSequenceTrue =「C1234R5678-C1234R9999」; string testSequenceFalse =「C1234R5678-C1234R5678」; 正則表達式objCategoryMatchShouldBeTrue = new Regex(regEx); bool isTrue = objCategoryMatchShouldBeTrue.IsMatch(testSequenceTrue); 正則表達式objCategoryMatchShouldBeFalse = new Regex(regEx); bool isFalse = objCategoryMatchShouldBeFalse.IsMatch(testSequenceFalse); – user295197 2012-01-13 02:54:38

+0

好吧,搞砸後,我得到了一些調整的結果。你們都非常鼓舞人心,並且使得這項工作比我想象的更容易實施。乾杯! – user295197 2012-01-13 04:03:08

+0

Ack。我希望我能以某種方式將這個獎項分開。我用了兩件都得到這個工作。 – user295197 2012-01-13 04:05:22