2015-06-19 68 views
1

其意圖是創建一個正則表達式,用於解析給定字符串中包含(..)和獨佔(...)範圍。爲什麼這個範圍的正則表達式失敗?

我的邊緣情況如下:

  1. 範圍的initialfinal值不能包含空格。
  2. 只接受(..)和獨家(...)範圍。
  3. final值的開頭不能包含點(.)。
  4. 整個字符串應該是一個有效的範圍。

這就是說,具有一定範圍的無效表示的字符串將是:

  • "1 2..20""1 2...20""12..2 0"
  • "1....10"" 1.10`

這是常規我到目前爲止的表情

/\A([^.\s]+)(\.{2,3})([^.][^\s]+)\z/

但它失敗。看起來原因是第三捕獲組中的[^.]部分。沒有[^.],它工作得很好,但不幸的是並沒有涵蓋所有的情況。

我在使用Ruby 2.2.1。

+0

在該範圍的端點任意表達式,或者他們是恆定的整數? – nneonneo

+0

端點不僅限於整數。一個有意義的案例:'「2015-06-10 ... 2015-06-19」'日期範圍。 – yeyo

+1

以句號開頭的數字在Ruby中不僅在範圍之後,而且在任何地方都是無效的。你確定條件3嗎? – sawa

回答

2

嘗試

/\A([^\s]*[^.])(\.{2,3})([^.][^\s]*)\z/ 

它使用*代替+,使第三捕獲組被允許只捕獲一個字符(以前的表達需要它來捕捉至少兩個字符)。

+0

哦!那是它......我的正則表達式中一個有趣的錯誤,的確如此。 – yeyo

0

這將允許您確定字符串是否表示整數或日期對象的有效範圍,如果是,則返回範圍。

代碼

R =/
    \A  # match beginning of string 
    (.+?)  # match one or more characters lazily in capture group 1 
    (\.{2,3}) # match 2 or 3 dots in capture group 2 
    ([^.]+) # match any characters other than dot in capture group 3 
    \z  # match end of string 
    /x  # extended mode 

require 'date' 

def convert_to_range(str) 
    str[R] 
    return nil unless $1 
    e1 = $1.strip 
    e2 = $3.strip 
    exclude_end = ($2.size == 3) 
    return nil if e1[/\s/] || e2[/\s/] 

    # Range of integers? 
    return rng(e1.to_i, e2.to_i, exclude_end) if e1[/\A\d+\z/] && e2[/\A\d+\z/] 

    # Range of dates? 
    begin 
    d1 = Date.parse(e1) 
    d2 = Date.parse(e2) 
    return rng(d1, d2, exclude_end) 
    rescue ArgumentError 
    end 

    nil 
end 

def rng(e1,e2,exclude_end) 
    Range.new(e1, e2, exclude_end) 
end 

例子

convert_to_range " 1 .. 20 " 
    #=> 1..20 
convert_to_range "1...20" 
    #=> 1...20 
convert_to_range "20..1" 
    #=> 20..1 
convert_to_range("20..1").size 
    #=> 0 
convert_to_range "1 2..20" 
    #=> nil 
convert_to_range "1 2...20" 
    #=> nil 
convert_to_range "12..2 0" 
    #=> nil 
convert_to_range "1....10" 
    #=> nil 
convert_to_range "1.10" 
    #=> nil 
convert_to_range "1.10" 
    #=> nil 

convert_to_range "2015-06-10...2015-06-19" 
    #=> #<Date: 2015-06-10 ((2457184j,0s,0n),+0s,2299161j)>... 
    # #<Date: 2015-06-19 ((2457193j,0s,0n),+0s,2299161j)> 
convert_to_range "2015-06-19...2015-06-10" 
    #=> #<Date: 2015-06-19 ((2457193j,0s,0n),+0s,2299161j)>... 
    # #<Date: 2015-06-10 ((2457184j,0s,0n),+0s,2299161j)> 
convert_to_range "2015-06-10...cat" 
    #=> nil 
+0

你的答案只涵蓋整數。例如,不能將日期範圍「2015-06-10 ... 2015-06-19」轉換。順便說一句,這是一個美麗的方法!它給了我一些想法,雖然我已經做了我的日期支持。 http://pastebin.com/czW0fjH6 – yeyo

+0

我做了一些更改以解決您的評論。 –

+0

一個區別是你的代碼有數據類型作爲參數,而我確定它是整數還是來自字符串的日期。 –