检查Ruby中多个正则表达式条件的更好方法是什么?

时间:2015-02-04 00:19:56

标签: ruby regex

我正在寻找一种更好的方法来检查,如果一个字符串匹配多个正则表达式模式(或不匹配)。 到目前为止,这是我的方法:

class Bob
  def hey(remark)
    if remark =~ upcase && !(remark =~ downcase) && !(remark =~ numbers)
      'Whoa, chill out!'
    elsif remark =~ ends_with_questionmark
      'Sure.'
    elsif (remark =~ numbers) && (remark =~ upcase) && !(remark =~ downcase)
      'Whoa, chill out!'
    else
      'Whatever.'
    end 
  end
  def numbers
    /[\d]+/
  end
  def downcase
    /[a-z]+/
  end
  def upcase
    /[A-Z]+/
  end
  def ends_with_questionmark
    /[\?]$/
  end
end

3 个答案:

答案 0 :(得分:3)

我发现很难理解Bob#hey正在做什么。一种可能性是在String类中定义一些适当命名的辅助方法:

class String
  def contains_a_digit?()            !!(self =~ /\d/)        end
  def contains_no_digits?()          !self.contains_a_digit? end
  def contains_an_uppercase_char?()  !!(self =~ /[A-Z]/)     end
  def contains_no_lowercase_chars?() self !~ /[a-z]/         end
  def ends_with_questionmark?()      !!(self =~ /[\?]$/)     end
end

请注意(例如)self =~ /\d+/self =~ /\d/在这里可以互换;当且仅当self包含至少一个数字时,两者都返回真值。顺便提一下,接收器self必须在这里明确。

除了不熟悉!!的读者:如果truthy是包含falsenil!!(truthy) => true!!(nil) => false以外的任何值的变量}和!!(false) => false。换句话说,!!是将truthy值转换为true而将falsy值转换为false(我仅用于提高可读性)的技巧。

让我们试试这些方法:

str = 'U2d?'                     #=> "U2d?" 
str.contains_a_digit?            #=> true 
str.contains_no_digits?          #=> false 
str.contains_an_uppercase_char?  #=> true 
str.contains_no_lowercase_chars? #=> false 
str.ends_with_questionmark?      #=> true 

使用Ruby 2.1+,如果有人不愿意修补String类,可以使用Refinements

现在可以用自然方式定义方法Bob#hey

class Bob
  def hey(remark)
    case
    when remark.contains_no_digits? &&
         remark.contains_an_uppercase_char? &&
         remark.contains_no_lowercase_chars?
      'Whoa, chill out! (1st)'
    when remark.ends_with_questionmark?
      'Sure.'
    when remark.contains_a_digit? &&
         remark.contains_an_uppercase_char? &&
         remark.contains_no_lowercase_chars?
      'Whoa, chill out! (2nd)'
    else
      'Whatever.'
    end
  end
end

试试吧。

bob = Bob.new
bob.hey("I PAID IN $US!")   #=> "Whoa, chill out! (1st)" 
bob.hey("What's that?")     #=> "Sure." 
bob.hey("I FLEW ON A 777!") #=> "Whoa, chill out! (2nd)" 
bob.hey("I give up.")       #=> "Whatever." 

答案 1 :(得分:1)

我认为一般来说,2 else以上应该是case

def hey remark
  case
    when remark =~ upcase && !(remark =~ downcase) && !(remark =~ numbers) then 'Whoa, chill out!'
    when remark =~ ends_with_questionmark then 'Sure.'
    when (remark =~ numbers) && (remark =~ upcase) && !(remark =~ downcase) then 'Whoa, chill out!'
    else 'Whatever.'
  end
end

但我也认为这些正则表达式需要工作,他们可能不会按照你的想法行事。

您也可以将!(str =~ /re/)更改为str !~ /re/

答案 2 :(得分:0)

您的代码可以像这样重写

def hey(remark)
    if remark =~  /[A-Z]+/
      'Whoa, chill out!'
    elsif remark =~  /[\?]$/
      'Sure.'
    else
      'Whatever.'
    end 
  end