我有以下潜在的字符串:
最多200小时
最多13小时40分钟 ...
现在我可以找到以下正则表达式的小时数:
/Up to (\d+) h/.match("Up to 200 h")
然而,对于其他类型的入口,我也可以有分钟,我没有看到如何建立正则表达式。
最后我希望总持续时间以分钟为单位,所以:
Up to 200 h ---> 200*60
Up to 13 h 40 min ---> 13*60 + 40
答案 0 :(得分:1)
使用可选组((...)?
):
m = /Up to (\d+) h\b(?: (\d+) min)?/.match('Up to 200 h')
# => #<MatchData "Up to 200 h" 1:"200" 2:nil>
m[1]
# => "200"
m[2]
# => nil
m[1].to_i * 60 + m[2].to_i
# => 12000
m = /Up to (\d+) h\b(?: (\d+) min)?/.match('Up to 13 h 40 min')
# => #<MatchData "Up to 13 h 40 min" 1:"13" 2:"40">
m[1]
# => "13"
m[2]
# => "40"
m[1].to_i * 60 + m[2].to_i
# => 820
m = /Up to (\d+) h\b(?: (\d+) min)?/.match('Up to 3 hippopotamuses')
# => nil
答案 1 :(得分:1)
这有效(但故意不确保该行开始或包含“最多”):
_, h, _, m = s.match(/(?:^|\s)(\d+)\s+h(\s+(\d+)\s+min)?(?:\s|$)/).to_a
s = "Up to 13 h abc"
_, h, _, m = s.match(/(?:^|\s)(\d+)\s+h(\s+(\d+)\s+min)?(?:\s|$)/).to_a
#=> [" 13 h ", "13", nil, nil]
# h => "13", m => nil
s = "Time until 13 h 40 min"
_, h, _, m = s.match(/(?:^|\s)(\d+)\s+h(\s+(\d+)\s+min)?(?:\s|$)/).to_a
# => ["13 h 40 min", "13", " 40 min", "40"]
# h => "13", m => "40"
s = "I was chased by 3 hippopotamuses"
_, h, _, m = s.match(/(?:^|\s)(\d+)\s+h(\s+(\d+)\s+min)?(?:\s|$)/).to_a
#=> []
(?:..)
表示非捕获组。一开始就有一个,最后一个。开头的那一个后面是捕获组1,它捕获第一个数字串(?:^|\s)(\d+)
。这些数字前面必须是行首(^
)或(|
)空白字符(\s
)。
第一组捕获的数字字符串必须后跟一个或多个空白字符,然后是字母h
(但不会捕获)。
在h
:(\s+(\d+)\s+min)?
后跟踪群组2。由于最后的问号,如果可能,将进行捕获,但正则表达式不需要成功。这是因为会议纪要可能存在,也可能不存在。
此捕获组包含捕获组3 (\d+)
,捕获组分钟值(如果捕获2已生成)。数字前面必须至少有一个空白字符,后跟至少一个空白字符,然后是"min"
。
如果捕获组2和3(分钟)进行捕获,则非捕获组(?:\s|$)
要求min
后跟空格或行尾。
如果捕获组2和3未进行捕获,(?:\s|$)
要求字母h
后跟空格或行尾。
"Time until 13 h 40 min".match(/.../).to_a
返回数组
#=> ["13 h 40 min", "13", " 40 min", "40"]
其中“13”,“40分钟”和“40”分别由组1,2和3捕获。由于我们需要捕获1和3,我们设置
_, h, _, m = s.match(/.../).to_a
答案 2 :(得分:0)
或者您可以在正则表达式中使用替代运算符(或),如下所示:
(\d+ h|\d+ min)
或包括这样的秒:
(\d+ h|\d+ min|\d+ sec)
这是一个“全局”匹配,所以在ruby中你使用.scan()
就像这样:
$m = "Up to 13 h 40 min 5 sec".scan(/(\d+ h|\d+ min|\d+ sec)/)
然后使用条件(如果那样)检查m [1],m [2],m [3]。