2010-05-07 15 views
0

我有這樣一個字符串「{一些|話|被|這裏}」和「{其他|設置|的|詞}」紅寶石參數化的正則表達式

所以在一般的字符串由左大括號的,由管道和結束的大括號分隔的單詞。

什麼是獲得該字符串的選定單詞的最有效方法?

我願做這樣的事情:

@my_string = "{this|is|a|test|case}" 
@my_string.get_column(0) # => "this" 
@my_string.get_column(2) # => "is" 
@my_string.get_column(4) # => "case" 

應該採取什麼方法get_column包含哪些內容?

+2

條形支撐,在管道上分開。你可能的意思是'get_column(2)'=>''a'' – SilentGhost 2010-05-07 14:38:14

回答

2

因此,這是解決方案,我喜歡現在:

class String 
    def get_column(n) 
    self =~ /\A\{(?:\w*\|){#{n}}(\w*)(?:\|\w*)*\}\Z/ && $1 
    end 
end 

我們使用正則表達式,以確保該字符串格式是正確的,同時抓住了正確的列。

說明正則表達式的:

  • \A是字符串的beginnning和\Z是結尾,所以此正則表達式的enitre字符串匹配。
  • 由於花括號具有特殊含義,我們將它們轉義爲\{\}以匹配字符串開頭和末尾的花括號。
  • 接下來,我們要跳過前n列 - 我們不關心它們。
    • 以前的專欄是字母后跟豎線一些數字,所以我們使用標準\w匹配一個字狀的字符(包括數字和下劃線,但爲什麼不)和*匹配任何數量的人。垂直條有特殊的含義,所以我們必須將其作爲\|轉義。由於我們想對此進行分組,因此我們將其全部包含在非捕獲夥伴(?:\w*\|)?:使其不捕獲)。
    • 現在我們有n以前的列,所以我們告訴正則表達式匹配使用計數正則表達式的列模式n次 - 只需在花括號後面放置一個數字。我們使用標準的字符串substition,所以我們只是把{#{n}}表示「符合以前的模式正好n倍。
  • 第一個非跳過欄後,這是我們關心的一個,所以我們把在捕獲括號:(\w*)
  • 那麼我們跳過列的其餘部分,如果有的話:(?:\|\w*)*

捕獲柱將其放入$1,所以我們返回值,如果正則表達式匹配。如果沒有,我們返回零。 ,因爲這個String沒有n th柱。

在一般情況下,如果你想有更多的不僅僅是字在列(如"{a phrase or two|don't forget about punctuation!|maybe some longer strings that have\na newline or two?}"),那麼只需更換所有\w[^|{}]正則表達式,所以你可以在每個柱包含除了一個大括號或任何東西垂直酒吧。


這裏是我以前的解決方案

class String 
    def get_column(n) 
    raise "not a column string" unless self =~ /\A\{\w*(?:\|\w*)*\}\Z/ 
    self[1 .. -2].split('|')[n] 
    end 
end 

我們使用了類似的正則表達式,以確保該字符串包含一組列或引發錯誤。然後,我們從正面和背面剝離花括號(使用self[1 .. -2]限制從第一個字符開始到最後一個結束的子字符串),使用管道字符拆分列(使用.split('|')創建一個列數組) ,然後找到第n列(使用標準的數組查找[n])。

我只是想,只要我使用正則表達式來驗證字符串,我不如使用它來捕獲列。