2015-06-19 62 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

一个区别是你的代码有数据类型作为参数,而我确定它是整数还是来自字符串的日期。 –

相关问题