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


使用 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}""}

这将产生以下输出:

r1: - "password"         r2: - "password"
r1: + "1password"        r2: - "1password"
r1: + "password1"        r2: - "password1"
r1: + "pass1word"        r2: - "pass1word"
r1: + "password 1"       r2: + "password 1"

1.) 为什么结果不同?

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

这是由几个正则表达式功能和 Unicode 之间的交互引起的。 W都是非单词字符,其中包括 212A - "开尔文符号"(PDF 链接)和 017F - "拉丁小写字母 LONG S"ſ(PDF 链接)。/i添加了这两个字符的小写版本,它们是"正常"ks字符(006B - "拉丁小写字母 K"和 0073"拉丁小写字母 S"(PDF 链接))。

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

请注意,这似乎仅在W位于字符类中时才会发生(即 [W])。我也只能在irb中重现这一点,在独立脚本中,它似乎按预期工作。

有关详细信息,请参阅有关此内容的 Ruby 错误。

最新更新