正则表达式“char类错误中的空范围”

我的代码中有一个正则表达式,它匹配url的模式并抛出错误:

/^(http|https):\/\/([\w-]+\.)+[\w-]+([\w- .\/?%&=]*)?$/ 

错误是“char类错误中的空范围”。 我找到了原因([\w- .\/?%&=]*)? 部分。 Ruby似乎认识到了-\w- . 作为范围的运算符而不是字面值- 。 在向破折号添加转义后,问题就解决了。

但最初的正则表达式在我的同事的机器上运行良好。 我们使用相同版本的osx,rails和ruby:Ruby版本是ruby 1.9.3p194,rails是3.1.6,osx是10.7.5。 在我们将代码部署到我们的Heroku服务器之后,一切都运行良好。 为什么我的环境只有这个正则表达式的错误? Ruby正则表达式解释的机制是什么?

我可以在使用rvm 1.13.4安装在Ubuntu 12.04.1 LTS上的Ruby 1.9.3p194(2012-04-20修订版35410)[i686-linux]上复制此错误。 但是,这不应该是特定于版本的错误。 事实上,我很惊讶它在其他机器上工作。

一个简单的演示也失败了:

 "abcd" =~ /[\w- ]/ 

这是因为[\w- ]被解释为“以任何单词字符开头到空格(或空白)”的范围,而不是包含单词,连字符或空格的字符类,这是您的意图。

Per Ruby的正则表达式文档 :

在字符类中,连字符( – )是表示包含范围的字符的元字符。 [abcd]相当于[ad]。 范围后面可以跟另一个范围,因此[abcdwxyz]相当于[a-dw-z]。 范围或单个字符在字符类中出现的顺序无关紧要。

如您所见,前缀反斜杠转义了连字符,从而将正则表达式的性质从范围更改为字符类,从而消除了错误。 但是,不建议在字符类中间转义连字符,因为在这种情况下很容易混淆连字符的预期含义。 正如m.buettner指出的那样,始终将连字符放在字符类的开头或结尾:

 "abcd" =~ /[-\w ]/