表示特定字符串的正则表达式,表示时间的数字



谁能帮帮我?我有一个字符串格式:10 mins - 20 mins1 min - 10 mins10 mins - 1 hour10 mins - 1 hour 30 mins10 mins - 2 hours10 mins - 2 hours 30 mins。我想为所有格式创建一个正则表达式,但我不能:失望:。请帮助我,非常感谢。

上述所有格式的正则表达式。

我可能会先在破折号上分割,然后使用相同的正则表达式匹配两边的组件。

"1 hour 10 mins - 3 hours".split(/s+-s+/, 2).map do |s| 
s.scan(
/
d+ s+ mins
| d+ s+ hour(?=s?)
| d+ s+ hour(?=s?) 
s+ 
d+ s+ min(?=s?)
/x
) 
end
# => [["1 hour", "10 mins"], ["3 hour"]]
"1 hour 10 mins - 40 mins".split(/s+-s+/, 2).map do |s| 
s.scan(
/
d+ s+ mins
| d+ s+ hour(?=s?)
| d+ s+ hour(?=s?) 
s+ 
d+ s+ min(?=s?)
/x
) 
end
# [["1 hour", "10 mins"], ["40 mins"]]

我假设:

  • 每个字符串在负号左边只包含分钟(不包含小时);和
  • 小时(如有)在1到9之间。

这些假设与问题中给出的例子是一致的。


然后可以使用字符串#match和MatchData#named_capture与正则表达式

rgx = /(?<lmin>(?:[1-9]|[1-5]d)) mins? - (?:(?<hr>[1-9]) hours?(?: (?<rminwhr>g<lmin>) mins?)?|(?<rminwohr>g<lmin>) mins?)/

提取感兴趣的值。让我们用问题中给出的例子来试一试。

["10 mins - 20 mins",
"1 min - 10 mins",
"10 mins - 1 hour",
"10 mins - 1 hour 30 mins",
"10 mins - 2 hours",
"10 mins - 2 hours 30 mins"].each do |str|
m = str.match(rgx)
puts str
puts "str.match(rgx) = #{m.inspect}"
puts "captures = #{m.named_captures}"
puts
end

显示如下。

10 mins - 20 mins
str.match(rgx) = #<MatchData "10 mins - 20 mins" lmin:"20" hr:nil rminwhr:nil rminwohr:"20">
captures = {"lmin"=>"20", "hr"=>nil, "rminwhr"=>nil, "rminwohr"=>"20"}
1 min - 10 mins
str.match(rgx) = #<MatchData "1 min - 10 mins" lmin:"10" hr:nil rminwhr:nil rminwohr:"10">
captures = {"lmin"=>"10", "hr"=>nil, "rminwhr"=>nil, "rminwohr"=>"10"}
10 mins - 1 hour
str.match(rgx) = #<MatchData "10 mins - 1 hour" lmin:"10" hr:"1" rminwhr:nil rminwohr:nil>
captures = {"lmin"=>"10", "hr"=>"1", "rminwhr"=>nil, "rminwohr"=>nil}
10 mins - 1 hour 30 mins
str.match(rgx) = #<MatchData "10 mins - 1 hour 30 mins" lmin:"30" hr:"1" rminwhr:"30" rminwohr:nil>
captures = {"lmin"=>"30", "hr"=>"1", "rminwhr"=>"30", "rminwohr"=>nil}
10 mins - 2 hours
str.match(rgx) = #<MatchData "10 mins - 2 hours" lmin:"10" hr:"2" rminwhr:nil rminwohr:nil>
captures = {"lmin"=>"10", "hr"=>"2", "rminwhr"=>nil, "rminwohr"=>nil}
10 mins - 2 hours 30 mins
str.match(rgx) = #<MatchData "10 mins - 2 hours 30 mins" lmin:"30" hr:"2" rminwhr:"30" rminwohr:nil>
captures = {"lmin"=>"30", "hr"=>"2", "rminwhr"=>"30", "rminwohr"=>nil}

lmin读取"负号左几分钟;rminwhr(rminwohr)读取"分钟"到带(不带)小时的负号右侧。


可以在这里看到正则表达式的演示。将光标悬停在正则表达式上,可以看到表达式各部分的功能说明。这些结果显示在PCRE正则表达式引擎上,但它们对于Ruby的正则表达式引擎(Oniguruma)也是一样的。


我们可以将正则表达式写成自由空格模式以使其自文档化。

/
(?<lmin>        # begin capture group 'lmin'
(?:           # begin non-capture group
[1-9]       # match a digit other than zero 
|           # or
[1-5]d     # match a digit between 1 and 5, followed by a digit
)             # end non-capture group
)               # end capture group 'lmin'
[ ]mins?        # match a space followed by 'min', 's' optional
[ ]-[ ]        # match ' - '
(?:             # begin non-capture group
(?<hr>        # begin capture group 'hr'
[1-9]       # match a digit other than zero
)             # end capture group 'hr'
[ ]hours?     # match a space followed by 'hour', 's' optional
(?:           # begin a non-capture group
[ ]         # match a space
(?<rminwhr> # begin capture group 'rminwhr'
g<lmin>  # invoke subexpression 'lmin'
)           # end capture group 'rminwhr'
[ ]mins?    # match a space followed by 'min', 's' optional
)             # end non-capture group
?             # make the preceding non-capture group optional
|             # or
(?<rminwohr>  # begin capture group 'rminwohr'
g<lmin>    # invoke subexpression 'lmin'
)             # end capture group 'rminwohr'
[ ]mins?      # match a space followed by 'min', 's' optional
)               # end non-capture group
/x              # invoke free-spacing regex definition mode

g<lmin>导致在该位置重用用于创建名为lmin的命名捕获组的代码。这被称为"子表达式"。或";subrouting"。有关说明,请搜索"子表达式"。在Regexp。子表达式的使用减少了表达式的大小,使其更容易阅读并减少了错误的机会,特别是在将来修改表达式时。

请注意,在自由间距模式下,作为表达式一部分的空格必须以某种方式加以保护,以防止它们在解析表达式之前被剥离。我选择将每个字符放在一个字符类中,但是还有其他方法可以做到这一点(例如,转义空格字符)。

相关内容

  • 没有找到相关文章

最新更新