ruby 正则表达式表示某个字符串,数字表示时间

6gpjuf90  于 2022-12-12  发布在  Ruby
关注(0)|答案(2)|浏览(140)

有谁能帮助我吗?2我有一个字符串,格式为:10 mins - 20 mins OR 1 min - 10 mins OR 10 mins - 1 hour OR 10 mins - 1 hour 30 mins OR 10 mins - 2 hours OR 10 mins - 2 hours 30 mins。我想为所有格式创建一个正则表达式,但我不能:很失望:.请帮我,谢谢。
一个正则表达式可能与所有上述格式。

kfgdxczn

kfgdxczn1#

我可能会先在破折号上拆分,然后使用相同的正则表达式匹配每一侧的组件。
例如:

"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"]]
0pizxfdo

0pizxfdo2#

我假设:

  • 每个字符串在减号左边只包含分钟(而不是小时);和
  • 小时,如果存在的话,在1和9之间。

这些假设与问题中的例子是一致的。
然后,可以将String#match和MatchData#named_captures与正则表达式一起使用

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表示“减号左边的分钟数”; rminwhrrminwohr)读取“减号右侧的分钟数,带(不带)小时”。
我们可以看到正则表达式here的演示。将光标悬停在正则表达式上,可以看到表达式每个部分的功能说明。这些结果是针对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的已命名捕获组的代码在该位置重用。这称为“子表达式”或“子路由”。有关说明,请在Regexp中搜索“子表达式”。使用子表达式可以减小表达式的大小,使其更易于阅读,并减少出错的机会,尤其是在将来修改表达式时。
注意,在自由空格模式下,表达式中的空格必须以某种方式加以保护,以防止它们在表达式被解析之前被删除。我选择将每个空格放在一个字符类中,但还有其他方法可以做到这一点(例如,对空格字符进行转义)。

相关问题