2010-10-03 77 views
1

我有一些字符串,我想模式匹配,然後提取出的匹配,而變量$ 1,$ 2,等如何從Ruby正則表達式提取可變數量的子匹配?

模式匹配的代碼,我是

a = /^([\+|\-]?[1-9]?)([C|P])(?:([\+|\-][1-9]?)([C|P]))*$/i.match(field) 

提出result = #{a.to_a.inspect}

利用上述我能夠容易地匹配以下樣品字符串:

「C」, 「+ 2C」, 「2C-P」, 「2C-3P」, 「P + C」

我已經在Rubular網站上確認了所有這些工作。
然而,當我嘗試匹配「+ 2P-C-3P」,但是,由於它匹配,MatchData「類似數組的對象」是這樣的:

result = ["+2P-C-3P", "+2", "P", "-3", "P"] 

的問題是,我不能提取到數組中,中間模式「-C」。

我希望看到的是:

result = ["+2P-C-3P", "+2", "P", "-", "C", "-3", "P"] 

它似乎只提取部「-3P」爲「-3」和「P」

有誰知道我可以修改我的模式來捕捉中間的比賽?
因此,作爲一個其他例子,+ 3C + 2P-C-4P,我希望應該創建:

["+3c+2p-c-4p", "+3", "C", "+2", "P", "-", "C", "-4", "P"] 

但我得到的是

["+3c+2p-c-4p", "+3", "C", "-4", "P"] 

它完全忽略了中間環節。

+0

我刪除了我的答案,因爲我看到它不是很正確。我會在幾分鐘後處理並重新發布。 – ubiquibacon 2010-10-03 08:02:28

+0

謝謝。我試過了,沒有,抱歉沒有奏效。 – 2010-10-03 08:03:34

回答

1

這是我能夠做到的:

([+-]?\d?)(C|P)(?=(?:[+-]?\d?[CP])*$) 

這樣你捕捉多個元素。
唯一的問題是字符串的有效性。由於紅寶石沒有外觀,我不能檢查字符串的開始,所以zerhyju+2P-C-3P是有效的(但只會捕獲+2P-C-3P),而+2P-C-3Pzertyuio是無效的。

如果你想捕獲和檢查,如果你的字符串是有效的,最好的辦法(IMO)是使用兩個正則表達式,一個檢查值^(?:[+-]?\d?[CP])*$和第二個捕獲([+-]?\d?)(C|P)(您也可以使用([CP])爲最後一部分)。

+0

我剛試過這個,它似乎在紅寶石網站上工作。讓我回顧一下你的答案。 「?=」是做什麼的? – 2010-10-03 08:16:07

+0

+1使用兩個正則表達式是我提出的分割和循環建議的另一種方法。不知道爲什麼你用'(?:C | P)'代替'[CP]'。 – Tomalak 2010-10-03 08:16:14

+0

@Tomalak,我沒有真正想過。但是你是對的,用'[CP]'更清楚(它也被更新) – 2010-10-03 08:29:57

4

你對字符類的工作方式有着深刻的(但常見的)誤解。此:

[C|P] 

是錯誤的。除非你想匹配管道|個字符。角色班沒有變化 - 他們不像組。這將是正確的:

[CP] 

此外,還有在字符類沒有元字符,所以你只需要逃跑很少的字符(即右方括號]和破折號-,除非你把它在組的結尾)。所以,你的正則表達式簡化爲:

^([+-]?\d?)([CP])(?:([+-]?\d?)([CP]))*$ 

你的第二個誤解是,組數是動態的 - 你以某種方式有更多的羣體中的結果,因爲更多的比賽出現的字符串中。不是這種情況。

由於在正則表達式中有圓括號對,因此在結果中有完全一樣多的組(當然少了非捕獲組的數量)。在這種情況下,該數字是4.不多也不少。

如果一個組匹配多次,只保留上次匹配事件的內容。沒有辦法(在Ruby中)獲取該組的先前匹配事件的內容。

作爲一種替代方法,您可以將字符串正則分解爲其有意義的部分,然後在循環中解析它們以提取所有信息。

+0

非常翔實。 – ubiquibacon 2010-10-03 08:09:43

+0

感謝您的意見Tomalek,讓我檢討你的迴應。新的模式匹配,所以原諒我[C | P]的誤解。 – 2010-10-03 08:18:43