【问题标题】:Weirdness with gsubgsub 的奇怪之处
【发布时间】:2012-05-08 08:29:49
【问题描述】:

我试图使用gsub 删除rails 应用程序中字符串中的非单词字符。我使用了以下代码:

somestring.gsub(/[\W]/i, '')  #=> ""

但它实际上是不正确的,它也会删除字母k。正确的应该是:

somestring.gsub(/\W/i, '')  #=> "kkk"

但我的问题是包含上述代码的rails控制器的单元测试使用rspec不起作用,单元测试实际上通过了。所以我在 rspec 中创建了一个非常极端的测试用例

it "test this gsub" do
  'kkk'.gsub(/[\W]/i, '').should == 'kkk'
end

上面的测试用例应该失败,但它实际上通过了。这里有什么问题?为什么会通过测试?

【问题讨论】:

  • 为什么测试会失败?据我所知,/[\W]/i 是该任务的完全有效的正则表达式。在这种情况下,括号是不必要的,但它不会伤害任何东西。
  • 您是否真的在irb 中尝试过您的正则表达式? "kkk".gsub(..) 正常工作,结果是“kkk”,所以测试通过了。你期待的结果是什么?
  • @Casper 实际上,当运行'kkk'.gsub(/[\W]/i, '') 时,我得到""。相比之下,运行 'kkk'.gsub(/\W/i, '') 会返回 "kkk"
  • 哎呀? k 是一个“单词”字符。 \W 匹配 non-word 字符。在我的 Ruby 安装中,当在 irb 中运行时,我得到了 "kkk"
  • 看起来像。但是,如果您删除 /i 标志,一切都会正常工作。你真的需要非单词字符的忽略大小写标志吗?

标签: ruby regex rspec ruby-1.9 gsub


【解决方案1】:

Ruby 1.9 切换到不同的正则表达式引擎 (Oniguruma),这导致了行为变化。这似乎是一个错误。

对于您的示例,您可以通过不指定不区分大小写的匹配来解决此问题:

irb(main):001:0> 'kkk'.gsub(/[\W]/i, '')
=> ""
irb(main):002:0> 'kkk'.gsub(/[\W]/, '')
=> "kkk"
irb(main):004:0> 'kkk'.gsub(/\W/i, '')
=> "kkk"
irb(main):003:0> 'kkk'.gsub(/\W/, '')
=> "kkk"

更新:看起来移除字符组是另一种方法。可能是这样的否定匹配在字符组中不一定有效?

【讨论】:

  • 你认为......不,它不可能......它正在使用\W并使其变为\w,因为它不区分大小写?它实际上不可能这样做,对吧? O_O
  • 我希望不会……但你永远不会知道。这可能应该在bugs.ruby-lang.org 上提出,以确认责任在哪里
  • 这里也确认了错误rubular.com。你可以在 1.8.7 和 1.9.2 之间切换,看看有什么区别。
  • 这是一个已经存在的Ruby issue about this
  • 当正则表达式处于 unicode 模式时,这似乎是一个问题 - 我的猜测是您的 rails env 的默认编码与您的测试环境不同
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
  • 2021-01-08
  • 2011-10-24
  • 2017-12-14
相关资源
最近更新 更多