2012-11-26 3 views
6

は、私はIRBで、次のRubyのコードを持っている:これらの2つのほぼ同一のRuby正規表現パターンで異なる結果が表示されるのはなぜですか?また、一致しないと思われるものがあるのはなぜですか? Rubyの1.9.2を使用して

> 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]) lookaheadは、それらの例に単語以外の文字がないので失敗するでしょうか?

+0

'/ ^(?=。* [\ d])(?=。*([\ W]))。{8,20} $/i'と一致するようにしてください。グループ「1」をキャプチャしていますか? (私はそれが数字だとは思いますが、あなたは決して知りません) –

+0

Ruby 1.9.3-p327を使った結果:r1: - "password" r2: - "password" r1: - "1password" r2: - "1password" r1: - "password1" r2: - "password1" r1: - "pass1word" r2: - "pass1word" r1:+ "パスワード1" r2:+ "パスワード1" => ["password"、 "1password "、" password1 "、" pass1word "、" password 1 "] 1.9.2のバグを見つけたようですか? –

+0

質問に含めてください(適切な書式設定のために) –

答えて

6

これは、いくつかの正規表現の機能とUnicodeの間の相互作用に起因します。 \Wは、すべて単語以外の文字です(212A - "KELVIN SIGN" (PDF link)017F - "LATIN SMALL LETTER LONG S" ſ (PDF link)を含む)。 /iは、これらの両方の小文字のバージョンを追加します。これらのバージョンは、「通常の」ks006B - "LATIN SMALL LETTER K" and 0073 "LATIN SMALL LETTER S" (PDF link))です。

したがって、passwordsは、場合によっては非単語文字として解釈されます。

これは、\Wが文字クラス(つまり、[\W])である場合にのみ発生すると考えられます。また、私はirbでこれを再現することができます。スタンドアロンスクリプトの中では、期待どおりに動作するようです。

詳細については、the Ruby bug about thisを参照してください。

+1

良いキャッチ。問題ではないが、[実際の問題](https://bugs.ruby-lang.org/issues/4044#note-3)は 'ß'(' ss 'に折りたたまれている)ではないが、017F - ラテン小文字ロングS 's(これは単一の' s 'に折り畳まれている)。 – user123444555621

+0

@ Pumbaa80ありがとう、それは意味がある、私は答えを更新しました。私は[バグレポートの別のコメント]から 'ß'を取った(https://bugs.ruby-lang.org/issues/4044#note-9)。この場合、 'ß'も' password'の倍数でマッチしますが、実際のマッチは単一なので、おそらく 's'です。 – matt

+0

うわー、それは面白い機能です:)説明とバグレポートへのリンクをありがとう。 –

関連する問題