2016-12-01 68 views
2

的字符串是:1/9/2017麻烦与正则表达式

我的正则表达式是:/([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/

这里是我的代码行:

def session_formatter(string) 
    if string =~ /([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/ 
     year = $2 
     if $1 =~ /8|9|10|11/ 
     "Fall " + year 
     elsif $1 =~ /1|2|3/ 
     "Spring " + year 
     else 
     string 
     end 
    end 
    end 

1/9/2017返回而不是Spring 2017我想不通为什么。有任何想法吗?

+0

可以肯定一看这里,一个真棒工具来快速检查您的正则表达式:http://rubular.com – Roger

+0

让我知道,如果有人需要任何更多的信息 –

回答

2

而不是处理正则表达式我会使用:

str = '1/9/2017' 

mm, dd, yyyy = str.split('/') 
case mm.to_i 
when 1, 2, 3 
    "Spring #{yyyy}" 
when 8, 9, 10 
    "Fall #{yyyy}" 
else 
    str 
end 
# => "Spring 2017" 

正则表达式是伟大的,但人们爱用他们这么多,他们忽略方式的任务可能是做得更简单。并非所有的东西都是等待被正则表达式击中的钉子。

拆分/降低了视觉噪音,使​​用to_i可以更容易地阅读和理解when正在做什么。

或者,使用Date类,它有各种各样的善良:

require 'date' 

str = '1/9/2017' 

date = Date.strptime(str, '%m/%d/%Y') 
case date.month 
when 1, 2, 3 
    "Spring #{date.year}" 
when 8, 9, 10 
    "Fall #{date.year}" 
else 
    str 
end 
# => "Spring 2017" 

我用strptime因为日期格式不为世人一致。 Ruby作为一种国际语言,使用最常见的格式dd/mm/yyyy作为Date.parse(...),这在解析美国日期时可能会遇到问题。相反strptime让我迫使解析器将使用基于美国-MM/DD/YYYY形式:

require 'date' 

Date.strptime('31/12/2001', '%d/%m/%Y') # => #<Date: 2001-12-31 ((2452275j,0s,0n),+0s,2299161j)> 
Date.strptime('31/12/2001', '%m/%d/%Y') # => ArgumentError: invalid date 

# ~> ArgumentError 
# ~> invalid date 

注意,第一个例子落在猎物这个特殊问题。处理日期时,如果允许用户输入日期作为自由格式的字符串,则知道用户来自何处非常重要,因此您至少可以猜测这些值的顺序。更好,友好的解决方案是使用具有某种类型的日期选择器的表单,这会迫使订单进入您的代码所期望的状态。不正确地处理日期可能会造成重大的破坏,涉及时间或金钱的计算,而您只是不希望发生这种情况。

如果日期是文件中文本的一部分,那么处理起来要容易一些,因为它应该一致地格式化,但是顺序仍然很重要。

如果你真的坚持使用的模式,我会去了解它是这样的:

str = '1/9/2017' 
/(?<mm>[0-9]{1,2})\/[0-9]{1,2}\/(?<yyyy>[0-9]{4})/ =~ str 

mm # => "1" 
yyyy # => "2017" 

case mm.to_i 
when 1, 2, 3 
    "Spring #{yyyy}" 
when 8, 9, 10 
    "Fall #{yyyy}" 
else 
    str 
end 
# => "Spring 2017" 

或者,为了增加乐趣:

str = '1/9/2017' 
matches = /(?<mm>[0-9]{1,2})\/[0-9]{1,2}\/(?<yyyy>[0-9]{4})/.match(str) 

mm, yyyy = matches[:mm], matches[:yyyy] 

case mm.to_i 
when 1, 2, 3 
    "Spring #{yyyy}" 
when 8, 9, 10 
    "Fall #{yyyy}" 
else 
    str 
end 
# => "Spring 2017" 

见Ruby的Regexp文档“命名捕获组“。

+0

额外补充说:“好玩”使用块'String#match'形式:) – engineersmnky

1

您正在使用随后的正则表达式检查重写$1变量。将其分配给单独的变量并用于进一步检查。

def session_formatter(string) 
    if string =~ /([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/ 
     year = $2 
     month = $1 
     if month =~ /8|9|10|11/ 
     "Fall " + year 
     elsif month =~ /1|2|3/ 
     "Spring " + year 
     else 
     string 
     end 
    end 
    end 

Ruby demo

0

下面是使用正则表达式命名的分组和一个简单的哈希查找另一种解决方案:在正则表达式

TIME_OF_YEAR = { 'Winter' => [12,1,2], 
       'Spring' => [3,4,5], 
       'Summer' => [6,7,8], 
       'Fall' => [9,10,11]} 

def session_formatter(string) 
    string.match(/(?<month>[0-9]{1,2})\/[0-9]{1,2}\/(?<year>[0-9]{4})/) do |m| 
    TIME_OF_YEAR.detect {|_,v| v.include? (m[:month].to_i)}.first + " #{m[:year]}" 
    end 
end 

dates = ["1/9/2017", "2/9/2017", "3/9/2017", "4/9/2017", "5/9/2017", "6/9/2017", "7/9/2017", "8/9/2017", 
"9/9/2017", "10/9/2017", "11/9/2017", "12/9/2017"] 

puts dates.map {|d| session_formatter(d)} 

此使用命名分组和比赛的块的形式,让你查找一年的时间中TIME_OF_YEAR散列在一个很好的简洁的方式。

Demo