2012-11-26 21 views
6

Sử dụng Ruby 1.9.2, tôi đã mã của Ruby sau trong IRB:Tại sao tôi thấy các kết quả khác nhau cho hai mẫu regex Ruby gần như giống hệt nhau này, và tại sao một kết hợp những gì tôi nghĩ là không nên?

> 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}\""} 

Điều này dẫn đến kết quả như sau:

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

1.) Tại sao kết quả khác nhau?

2.) Tại sao r1 khớp với chuỗi 2, 3 và 4? Chẳng phải cái nhìn của (?=.*[\W]) khiến nó thất bại vì không có bất kỳ ký tự không phải từ nào trong những ví dụ đó sao?

+0

Bạn có thể thử khớp với '/^(? =. * [\ D]) (? =. * ([\ W])). {8,20} $/i' và cho biết sử dụng những gì được chụp trong nhóm chụp '1'? (Tôi sợ đó là chữ số, nhưng bạn không bao giờ biết) –

+0

Kết quả sử dụng Ruby 1.9.3-p327: r1: - "mật khẩu" r2: - "mật khẩu" r1: - "1password" r2: - "1password" r1: - "password1" r2: - "password1" r1: - "pass1word" r2: - "pass1word" r1: + "mật khẩu 1" r2: + "mật khẩu 1" => ["mật khẩu", "1 mật khẩu "," password1 "," pass1word "," password 1 "] Có vẻ như bạn đã tìm thấy lỗi với 1.9.2? –

+0

Bạn có thể đưa câu hỏi đó vào câu hỏi của bạn được không (vì mục đích định dạng thích hợp) –

Trả lời

6

Kết quả này từ tương tác giữa một vài tính năng regex và Unicode. \W là tất cả các ký tự không phải từ, bao gồm 212A - "KELVIN SIGN" (PDF link)017F - "LATIN SMALL LETTER LONG S" ſ (PDF link). /i thêm các phiên bản chữ thường của cả hai loại này, là các ký tự “bình thường” ks (006B - "LATIN SMALL LETTER K" and 0073 "LATIN SMALL LETTER S" (PDF link)).

Vì vậy, đó là s trong password được hiểu là ký tự không phải từ trong một số trường hợp nhất định.

Lưu ý rằng điều này dường như chỉ xảy ra khi \W thuộc lớp nhân vật (ví dụ: [\W]). Ngoài ra tôi chỉ có thể tái tạo điều này trong irb, bên trong một tập lệnh độc lập có vẻ như hoạt động như mong đợi.

Xem the Ruby bug about this để biết thêm thông tin.

+1

Bắt tốt. Không quan trọng, nhưng [vấn đề thực tế] (https://bugs.ruby-lang.org/issues/4044#note-3) không phải là 'ß' (được xếp thành' ss'), nhưng 017F - LATIN NHỎ LETTER LONG S 'ſ' (được xếp thành một' s'). – user123444555621

+0

@ Pumbaa80 Cảm ơn, điều đó có ý nghĩa hơn, tôi đã cập nhật câu trả lời. Tôi lấy 'ß' từ [bình luận khác về báo cáo lỗi] (https://bugs.ruby-lang.org/issues/4044#note-9). Trong trường hợp này 'ß' cũng sẽ khớp với vì các double-s trong' mật khẩu', nhưng đối sánh thực tế là một s duy nhất, vì vậy nó có thể là 'ſ'. – matt

+0

Wow, đó là một tính năng thú vị :) Cảm ơn bạn đã giải thích và liên kết đến báo cáo lỗi. –

Các vấn đề liên quan