目的是创建一个正则表达式,用于解析给定字符串中的包含(..
)和独占(...
)范围。
我的边缘案例如下:
initial
和final
值不能包含空格。..
)和排他性(...
)范围。final
值在开头不能包含点(.
)。 也就是说,一个范围无效的字符串将是:
"1 2..20"
,"1 2...20"
,"12..2 0"
"1....10"
或"
1.10` 这是我到目前为止的正则表达式
/\A([^.\s]+)(\.{2,3})([^.][^\s]+)\z/
然而它失败了。似乎原因是第三个捕获组中的[^.]
部分。如果没有[^.]
,它的效果非常好,但不幸的是并未涵盖所有情况。
我正在使用Ruby 2.2.1。
答案 0 :(得分:2)
尝试
/\A([^\s]*[^.])(\.{2,3})([^.][^\s]*)\z/
这使用*
代替+
,以便允许第三个捕获组只捕获一个字符(您之前的表达式要求它捕获至少两个字符)。
答案 1 :(得分: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