2013-11-04 132 views
1

我有這樣的正則表達式不想一些替代品正則表達式

("[^"]*")|('[^']*')|([^<>]+) 

當遞給該輸入字符串

<telerik:RadTab Text="RGB"> 

我想它匹配RGB。但是,由於最後一種選擇會導致較長的字符串,因此不會。

我最好要的是:

  1. 如果有雙引號串,與之相匹配的,包括雙引號。
  2. 否則,如果存在單引號的子字符串,則匹配它,包括單引號。
  3. 否則,如果有一個由尖括號包圍的字符串,則匹配它,不包括尖括號。

這個邏輯可以在一個正則表達式中完成嗎?

+1

也許你應該使用XML解析器。 –

+0

你可以使用多個正則表達式 – Alan

+0

你也許可以用反向查找來做到這一點,但爲什麼不嵌套它(測試引用的例子,如果沒有,檢查'<>')(你錯過了在上一次搜索中包含<>,所以它將匹配一行中的所有內容...) – beroe

回答

3
var strings = new[] 
     {"<telerik:RadTab Text=\"RGB\">", "<telerik:RadTab Text=RGB>", "<telerik:RadTab Text='RGB'>"}; 
    var r = new Regex("<([^<\"']+[^>\"']+)>|(\"[^\"]*\")|('[^']*')"); 
    foreach (var s1 in strings) 
    { 
     Console.WriteLine(s1); 
     var match = r.Match(s1); 
     Console.WriteLine(match.Value); 
     Console.WriteLine(); 
    } 
    Console.ReadLine(); 
+0

幾乎完美!除此之外,由於愚蠢的原因,周圍的< and >不應該是比賽的一部分。 :(我發現它們不是子組的一部分,所以也許這會足夠好......我會再回復你一點。 –

+0

給定的代碼在其他方面似乎很愚蠢......嘆息。我會接受你的回答,因爲它回答了我所問的問題。謝謝。 –

2

其中一個解決這個問題的方法是使用向前斷言:

(?=("[^"]*"))|(?=('[^']*'))|(?=<([^<>]+)>) 

讓我們分解的正則表達式來獲得更好的視野:

(?=    # zero-width assertion, look ahead if there is ... 
    ("[^"]*") # a double quoted string, group it in group number 1 
)    # end of lookahead 
|    # or 
(?=    # zero-width assertion, look ahead if there is ... 
('[^']*')  # a single quoted string, group it in group number 2 
)    # end of lookahead 
|    # or 
(?=    # zero-width assertion, look ahead if there is ... 
<([^<>]+)>  # match anything except <> between <> one or more times and group it in group number 3 
)    # end of lookahead 

你可能會認爲what in the world is he doing?,無問題我會進一步解釋你的正則表達式失敗的原因。

我們有以下字符串<telerik:RadTab Text="RGB">

<telerik:RadTab Text="RGB"> 
^ the regex engine starts here 
since there is no match with ("[^"]*")|('[^']*')|([^<>]+) 
it will look further ! 

<telerik:RadTab Text="RGB"> 
^ the regex engine will now take a look here 
it will check if there is "[^"]*", well obviously there isn't 
now since there is an alternation, the regex engine will 
check if there is '[^']*', meh same thing 
it will now check if there is [^<>]+, but hey it matches ! 

So your regex engine will "eat" it like so 
<telerik:RadTab Text="RGB"> 
^^^^^^^^^^^^^^^^^^^^^^^^^ and match this, by eating I mean it's advancing 
Now the regex engine is at this point 
<telerik:RadTab Text="RGB"> 
         ^and obviously, there is no match 
The problem is, you want it to "step" back to match "RGB" 
The regex engine won't go back for you :(

這就是爲什麼我們使用零寬度斷言與團體,它不會吃(不會提前),如果你使用一組先行裏面你仍然得到你的匹配組。

<telerik:RadTab Text="RGB"> 
^ So when it comes here, it will match it with (?=<([^<>]+)>) 
but it won't eat the whole matched string 
Now obviously, the regex needs to continue to look for other matches 
So it comes here: 
<telerik:RadTab Text="RGB"> 
^ no match 
<telerik:RadTab Text="RGB"> 
^no match 
..... 
until 
<telerik:RadTab Text="RGB"> 
        ^hey there is a match using (?=("[^"]*")) 
it will then advance further 
<telerik:RadTab Text="RGB"> 
        ^no match 
.... until it reaches the end 

當然,如果你有一個字符串像<telerik:RadTab Text="RGB'lol'">它仍然會匹配在雙引號值'lol'並把它放在組號碼2。

Online demo
                                                                                                                                                                                                                                                                                                              正則表達式的岩石!

+1

謝謝你,lookahead看起來像是一個非常有用的功能,並且你已經很好地解釋了它,我不會在這種情況下使用它,因爲代碼以另一種方式是愚蠢的。無論如何,謝謝。 –

1

編輯:考慮下面的正則表達式......

(\".*?\"|\'.*?\'|(?<=\<).*?(?=\>))