2011-10-28 37 views
3

我想用正則表達式來匹配一些文本。使用正則表達式 - 重複模式

下面的模式是我想要收集的。

@Identifier('VariableA', 'VariableB', 'VariableX', ..., 'VariableZ') 

我想抓住一個動態數量的變量,而不是固定的兩個或三個集合。 有沒有辦法做到這一點?我有一個現有的正則表達式:

\@(\w+)\W+(\w+)\W+(\w+)\W+(\w+) 

這將捕獲標識符和最多三個變量。

編輯:它只是我,還是正則表達式不像我讓他們那樣強大?

回答

3

你想使用scan這種事情。其基本模式是這樣的:

s.scan(/\w+/) 

這會給你所有的連續序列的數組,字字符:

>> "@Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')".scan(/\w+/) 
=> ["Identifier", "VariableA", "VariableB", "VariableX", "VariableZ"] 

你說你可能有任意東西,周圍的圖案的多個實例他們。您可以處理與嵌套scan S:

s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] } 

這將會給你一個數組的數組,每個內部數組將有「標識符」的部分爲第一要素,而「變量」部分作爲一個數組第二個元素。例如:

>> s = "pancakes @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ') pancakes @Pancakes('one','two','three') eggs" 
>> s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] } 
=> [["Identifier", ["VariableA", "VariableB", "VariableX", "VariableZ"]], ["Pancakes", ["one", "two", "three"]]] 

如果您可能面臨「變量」位內的轉義引號,那麼您需要更復雜的東西。


上表達的一些注意事項:

@   # A literal "@". 
(   # Open a group 
    \w+  # One more more ("+") word characters ("\w"). 
)   # Close the group. 
\(   # A literal "(", parentheses are used for group so we escape it. 
(   # Open a group. 
    [   # Open a character class. 
    ^)  # The "^" at the beginning of a [] means "not", the ")" isn't escaped because it doesn't have any special meaning inside a character class. 
    ]   # Close a character class. 
    +?   # One more of the preceding pattern but don't be greedy. 
)   # Close the group. 
\)   # A literal ")". 

你並不真的需要[^)]+?這裏,只是[^)]+會做,但我按習慣使用非貪婪形式,因爲這通常是我的意思。該分組用於分離@IdentifierVariable部分,以便我們可以輕鬆獲得所需的嵌套數組輸出。

+0

這是完美的!這正是我所尋找的解決方案。現在學習如何創建正則表達式!非常感謝! – Michael

+1

@Michael:我爲你添加了正則表達式的一些註釋。 –

+0

你是最棒的!我非常感謝這方面的幫助。我真的很想用Ruby和正則表達式來更流暢。我甚至不知道你可以在這樣的表達式中做一個邏輯NOT。真的,再次感謝! – Michael

0

但亞歷克斯認爲你的意思是你想四次捕捉同樣的東西。如果你想捕捉相同的模式,但不同的事情,那麼你可能要考慮兩件事情:

迭代。在Perl中,你可以說

while ($variable =~ /regex/g) { 

的「G」代表「全球」,並意味着每個正則表達式被調用時,它的一個/下/實例相匹配。

另一種選擇是遞歸。寫下您的正則表達式是這樣的:

/(what you want)(.*)/ 

然後,你必須引用1含有的第一件事,你可以推到一個數組,反向引用2,你會再改乘了,直到它不再匹配。

+0

全局標識符是否在Ruby中工作?我不認爲它確實如此。 – Michael

+0

http://stackoverflow.com/questions/2293032/ruby-doesnt-recognize-the-g-flag-for-regex – Dan

0

您可以簡單地使用(\w+)

鑑於輸入字符串 @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')

的結果將是:

  1. Identifier
  2. VariableA
  3. VariableB
  4. VariableX
  5. VariableZ

這將適用於任意數量的變量。

爲了將來的參考,玩Rubular正則表達式的想法是很容易和有趣的。

+0

一直玩Rubular,但似乎無法得到這個權利。我只需要標識符和變量。我可以通過逐個拾取字符串來手動提取這些數據,但是那麼正則表達式有什麼意義呢?另外你的解決方案太廣泛了,如果我在需要捕獲的時候或之前添加任何其他單詞或單詞數據,那麼我正在捕獲不必要的數據。 – Michael

0

所以你問是否有一種方法來捕獲標識符和任意數量的變量。我擔心你只能用支持捕獲的正則表達式引擎來做到這一點。請注意,捕獲捕獲組不是同一件事。你想記住所有的「變量」。這不能用簡單的捕獲組來完成。

我不知道Ruby是否支持這個,但我相信.NET和新的PERL 6支持它。

在你的情況下,你可以使用兩個正則表達式。一個用於捕獲標識符,例如^\s*@(\w+)

另一個捕獲所有變量例如result = subject.scan(/'[^']+'/)