【问题标题】:Ruby: What's the proper syntax for a boolean regex method?Ruby:布尔正则表达式方法的正确语法是什么?
【发布时间】:2020-07-13 19:11:26
【问题描述】:

检查字符串中的模式并在正则表达式匹配时返回 true 或 false 的方法的正确语法是什么?

基本思路:

def has_regex?(string)
    pattern = /something/i
    return string =~ pattern
end

用例:

if has_regex?("something")
    # woohoo
else
    # nothing found: panic!
end

【问题讨论】:

  • 您的代码按原样工作,所以我看不出您在问什么
  • 哈哈,我的错。我没有正确调试我的代码。感谢您指出应该很明显的内容。
  • 没有理由定义has_regex?,只需定义if "something" =~ /something/i
  • 我希望模式在它自己的方法中,因为我在多个地方重复使用它,并且我想避免声明一个全局变量。

标签: ruby regex syntax


【解决方案1】:

在你说的问题中:

... 检查字符串中是否存在模式的方法,如果正则表达式匹配,则返回 true 或 false

正如johannes 指出的那样,String=~ 如果模式不匹配,则返回nil,否则匹配单词在字符串中的位置。此外,他在 Ruby 中声明了除 nil 和 false 之外的所有内容 表现得像 true。这一切都是对的。

但是,它们完全是true 或false。因此,最后一步是将值强制为Boolean。这是通过将结果包装在双刘海中来实现的,返回 true。

def has_regex?(string)
    !!(string =~ /something/i)
end

【讨论】:

【解决方案2】:

你的代码看起来不错,但你可以写得更小。

String#=~ 的返回值是这样的:

  • nil 如果模式不匹配
  • 匹配词在字符串中的起始位置

在 Ruby 中,除了 nil 和 false 之外的所有内容在条件语句中的行为类似于 true,因此您可以编写

if string=~ pattern
  # do something
else
  # panic
end

【讨论】:

  • 您的答案适合所提供的用例,但没有正确回答 OP 的问题(这对来到这里的人很重要)。例如,在将结果分配给 ActiveRecord 对象时,这一点至关重要:role 为“admin”时,Foo.new(admin: (role =~ /admin/)).admin 返回 false,因为 =~ 返回 0,Rails 将其转换为 false。只是说。
【解决方案3】:

为了让它返回真/假,切换模式和字符串的位置以及用例相等===

def has_regex?(string)
    pattern = /something/i
    return pattern === string
end

我绝对需要它来返回真正的布尔值并四处挖掘。 它实际上记录在正则表达式类http://www.ruby-doc.org/core-2.1.3/Regexp.html#method-i-3D-3D-3D

【讨论】:

  • 这是最好的解决方案,但是,应该注意的是,当str 既不是String 也不是Symbol 时,regex === str 返回false 而其他解决方案在这里发布使用=~ 引发TypeError。
【解决方案4】:

如果您使用的是 Ruby 2.4 或更高版本,则有 String#match?(regex) 和 Regexp#match?(string) 方法可以返回布尔值而无需转换恶作剧(在需要时,通常不需要),并且提高了启动性能。

https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match-3F

https://blog.cognitohq.com/new-features-in-ruby-2-4/

【讨论】:

    【解决方案5】:

    对于 Ruby >= 2.4 或 Rails,您可以这样做:

     regexp.match?(string)
    

    【讨论】:

      【解决方案6】:

      将其添加到 String 类使其使用起来非常简单:

         class String
            def match?(regex)
                !!self.match(regex)
            end
         end
      

      我将它添加到 Rails 初始化程序(RAILS_ROOT/config/initializers)中,您可以直接从字符串中调用:

      "Something special!".match?(/something/i) #=> true 
      "Somethin' special!".match?(/something/i) #=> false 
      

      【讨论】:

        【解决方案7】:

        对于任何人的未来参考,bbatsov's ruby style guide 不赞成双刘海。不要使用双键,只需检查值是否不是 nil。如果值不为零,则存在。

        不要这样做:

        def has_regex?(string)
          !!(string =~ /something/i)
        end
        

        你总是可以这样做:

        def has_regex?(string)
          !(string =~ /something/i).nil?
        end
        

        【讨论】:

        • 也许(string =~ /something/i).present? 这样你就不用倒置它了吗?
        • 我更喜欢(string =~ /something/i) != nil,因为我觉得它更具可读性。
        • 请注意,present? 是一种 ActiveSupport 方法(即 Rails 的一部分),如果您只是使用常规 Ruby,则不可用。
        【解决方案8】:

        我没有足够的声誉来发表评论,所以我会代替回答。

        按照 viljar 的建议,the Ruby Style Guide 建议不要使用 ===,这会导致 Rubocop 投诉(在默认规则下)。

        我发现最易读的方式是:

        def match?(string)
          !(string =~ /something/i).nil?
        end
        

        【讨论】:

          【解决方案9】:

          因为我希望它能够正常工作,而不仅仅是针对任何特定项目,所以我根本不想修改环境。

          我能够通过简单地使用来自普通match 方法的返回值作为条件来使其工作。测试了这个示例字符串的正负大小写:

          irb(main):014:0> if "123".match(/.2./); puts "worked"; end
          worked
          => nil
          irb(main):015:0> if "123".match(/.3./); puts "worked"; end
          => nil
          

          【讨论】:

            【解决方案10】:

            如果你想把模式放在一个方法中,你可以这样做

            def has_my_pattern(st)
                st =~ /pattern/
            end
            

            或者,也许更好的是,将模式放在类变量中?

            【讨论】:

            • 这不返回布尔值。 @Ryan 的回答是正确的。
            猜你喜欢
            • 2014-08-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-18
            • 2015-06-26
            • 1970-01-01
            • 2013-04-07
            相关资源
            最近更新 更多