为什么我看到这两个几乎相同的Ruby正则表达式模式有不同的结果,为什么一个匹配我认为它不应该?

Chr*_*oom 6 ruby regex unicode character-class

使用Ruby 1.9.2,我在IRB中有以下Ruby代码:

> r1 = /^(?=.*[\d])(?=.*[\W]).{8,20}$/i
> r2 = /^(?=.*\d)(?=.*\W).{8,20}$/i
> a = ["password", "1password", "password1", "pass1word", "password 1"]
> a.each {|p| puts "r1: #{r1.match(p) ? "+" : "-"} \"#{p}\"".ljust(25) + "r2: #{r2.match(p) ? "+" : "-"} \"#{p}\""}
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

r1: - "password"         r2: - "password"
r1: + "1password"        r2: - "1password"
r1: + "password1"        r2: - "password1"
r1: + "pass1word"        r2: - "pass1word"
r1: + "password 1"       r2: + "password 1"
Run Code Online (Sandbox Code Playgroud)

1.)为什么结果不同?

2.)为什么r1匹配字符串2,3和4?(?=.*[\W])前瞻不会导致它失败,因为这些例子中没有任何非单词字符吗?

mat*_*att 6

这是由几个正则表达式功能和Unicode之间的交互产生的.\W是所有非单词字符,包括212A - "KELVIN SIGN" (PDF链接)017F - "LATIN SMALL LETTER LONG S" ſ(PDF链接).在/i增加了这两种的小写版本,分别是"正常的" ks字(006B - "拉丁小字母K"和0073"拉丁小字母S"(PDF链接)).

因此,在某些情况下s,password它被解释为非单词字符.

请注意,这似乎只发生\W在字符类(即[\W])中.此外,我只能irb在一个独立的脚本中重现它,它似乎按预期工作.

有关更多信息,请参阅有关此问题的Ruby错误.