首页 > 解决方案 > Ruby 正则表达式匹配 vs ===

问题描述

我正在练习中的红宝石轨道中进行 Bob 练习,我通过了所有测试,除了一个:

1) Failure:
BobTest#test_multiple_line_question [bob_test.rb:129]:
Bob hears "\nDoes this cryogenic chamber make me look fat?\nNo.", and...
Expected: "Whatever."
  Actual: "Sure."

25 runs, 25 assertions, 1 failures, 0 errors, 0 skips

这是我的代码:

# Class emulating teenager answers
class Bob
  def self.hey(remark)
    case remark
    when /^[A-Z| ]+\?$/
      'Calm down, I know what I\'m doing!'
    when /^.*\?[ ]*$/, /^\n.*?\nNo\./m
      'Sure.'
    when /^.*[A-Z]+!+.*$/, /^[A-Z]+[A-Z| ]*!*$/
      'Whoa, chill out!'
    when /^[ |\t]*$/
      'Fine. Be that way!'
    else
      'Whatever.'
    end
  end
end

所以我不知道如何处理这个正则表达式:

    q = "\nDoes this cryogenic chamber make me look fat?\nNo."
    #=> "\nDoes this cryogenic chamber make me look fat?\nNo."
    puts q
    # Does this cryogenic chamber make me look fat?
    # No.

    q.match?(/^\n.*?\nNo\./m)
    #=> true

    [4] pry(main)> [5] pry(main)> Bob.hey(q)
=> "Sure."
[7] pry(main)> class Bob
  def self.hey(remark)
    case remark
    when /^[A-Z| ]+\?$/
      'Calm down, I know what I\'m doing!'
    when /^.*\?[ ]*$/, /^\n.*?\nNo\./m
      'Sure.'
    when /^.*[A-Z]+!+.*$/, /^[A-Z]+[A-Z| ]*!*$/
      'Whoa, chill out!'
    when /^[ |\t]*$/
      'Fine. Be that way!'
    else
      'Whatever.'
    end
  end
end
[7] pry(main)* => :hey
[8] pry(main)> Bob.hey(q)
=> "Sure."

问题是 minitest 不起作用,我不明白为什么:

require 'minitest/autorun'
require_relative 'bob'

# Common test data version: 1.4.0 ca79943
class BobTest < Minitest::Test
  def test_stating_something
    # # skip
    remark = "Tom-ay-to, tom-aaaah-to."
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "Tom-ay-to, tom-aaaah-to.", and..}
  end

  def test_shouting
    # skip
    remark = "WATCH OUT!"
    assert_equal "Whoa, chill out!", Bob.hey(remark), %q{Bob hears "WATCH OUT!", and..}
  end

  def test_shouting_gibberish
    # skip
    remark = "FCECDFCAAB"
    assert_equal "Whoa, chill out!", Bob.hey(remark), %q{Bob hears "FCECDFCAAB", and..}
  end

  def test_asking_a_question
    # skip
    remark = "Does this cryogenic chamber make me look fat?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "Does this cryogenic chamber make me look fat?", and..}
  end

  def test_asking_a_numeric_question
    # skip
    remark = "You are, what, like 15?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "You are, what, like 15?", and..}
  end

  def test_asking_gibberish
    # skip
    remark = "fffbbcbeab?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "fffbbcbeab?", and..}
  end

  def test_talking_forcefully
    # skip
    remark = "Let's go make out behind the gym!"
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "Let's go make out behind the gym!", and..}
  end

  def test_using_acronyms_in_regular_speech
    # skip
    remark = "It's OK if you don't want to go to the DMV."
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "It's OK if you don't want to go to the DMV.", and..}
  end

  def test_forceful_question
    # skip
    remark = "WHAT THE HELL WERE YOU THINKING?"
    assert_equal "Calm down, I know what I'm doing!", Bob.hey(remark), %q{Bob hears "WHAT THE HELL WERE YOU THINKING?", and..}
  end

  def test_shouting_numbers
    # skip
    remark = "1, 2, 3 GO!"
    assert_equal "Whoa, chill out!", Bob.hey(remark), %q{Bob hears "1, 2, 3 GO!", and..}
  end

  def test_no_letters
    # skip
    remark = "1, 2, 3"
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "1, 2, 3", and..}
  end

  def test_question_with_no_letters
    # skip
    remark = "4?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "4?", and..}
  end

  def test_shouting_with_special_characters
    # skip
    remark = "ZOMG THE %^*@\#$(*^ ZOMBIES ARE COMING!!11!!1!"
    assert_equal "Whoa, chill out!", Bob.hey(remark), %q{Bob hears "ZOMG THE %^*@\#$(*^ ZOMBIES ARE COMING!!11!!1!", and..}
  end

  def test_shouting_with_no_exclamation_mark
    # skip
    remark = "I HATE THE DMV"
    assert_equal "Whoa, chill out!", Bob.hey(remark), %q{Bob hears "I HATE THE DMV", and..}
  end

  def test_statement_containing_question_mark
    # skip
    remark = "Ending with ? means a question."
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "Ending with ? means a question.", and..}
  end

  def test_non_letters_with_question
    # skip
    remark = ":) ?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears ":) ?", and..}
  end

  def test_prattling_on
    # skip
    remark = "Wait! Hang on. Are you going to be OK?"
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "Wait! Hang on. Are you going to be OK?", and..}
  end

  def test_silence
    # skip
    remark = ""
    assert_equal "Fine. Be that way!", Bob.hey(remark), %q{Bob hears "", and..}
  end

  def test_prolonged_silence
    # skip
    remark = "          "
    assert_equal "Fine. Be that way!", Bob.hey(remark), %q{Bob hears "          ", and..}
  end

  def test_alternate_silence
    # skip
    remark = "\t\t\t\t\t\t\t\t\t\t"
    assert_equal "Fine. Be that way!", Bob.hey(remark), %q{Bob hears "\t\t\t\t\t\t\t\t\t\t", and..}
  end

  def test_multiple_line_question
    # skip
    remark = "\nDoes this cryogenic chamber make me look fat?\nNo."
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "\nDoes this cryogenic chamber make me look fat?\nNo.", and..}
  end

  def test_starting_with_whitespace
    # skip
    remark = "         hmmmmmmm..."
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "         hmmmmmmm...", and..}
  end

  def test_ending_with_whitespace
    # skip
    remark = "Okay if like my  spacebar  quite a bit?   "
    assert_equal "Sure.", Bob.hey(remark), %q{Bob hears "Okay if like my  spacebar  quite a bit?   ", and..}
  end

  def test_other_whitespace
    # skip
    remark = "\n\r \t"
    assert_equal "Fine. Be that way!", Bob.hey(remark), %q{Bob hears "\n\r \t", and..}
  end

  def test_non_question_ending_with_whitespace
    # skip
    remark = "This is a statement ending with whitespace      "
    assert_equal "Whatever.", Bob.hey(remark), %q{Bob hears "This is a statement ending with whitespace      ", and..}
  end
end

标签: rubyregex

解决方案


你的参数是倒退的。===,在红宝石中,是一个有点奇怪的操作,因为它并不总是对称的 - 即仅仅因为a === b,它不一定是真的b === a

在这种情况下,请注意:

/^\n.*?\nNo\./ === "\nDoes this cryogenic chamber make me look fat?\nNo."
  => true

(和String === Regex总是返回假。)

这是case放置参数的顺序,并解释了为什么您会看到该结果。

但是,我真的不知道如何“修复”您的代码,因为我不知道您期望什么行为!也许测试是错误的?也许正则表达式是错误的?也许case陈述是错误的?


推荐阅读