2012-11-26 11 views
6

Utilizzando rubino 1.9.2, ho il seguente codice Ruby in IRB:Perché vedo risultati diversi per questi due modelli di regex di Ruby quasi identici, e perché uno corrisponde a ciò che penso che non dovrebbe?

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

Il risultato è il seguente output:

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

1.) Perché i risultati sono diversi?

2.) Perché r1 corrisponde alle stringhe 2, 3 e 4? Il lookheadhead (?=.*[\W]) non si risolverebbe perché non ci sono caratteri non di parole in quegli esempi?

+0

Potresti provare a cercare '/^(? =. * [\ D]) (? =. * ([\ W])). {8,20} $/i' e dire usare ciò che viene catturato nel catturare il gruppo '1'? (Temo che sia la cifra, ma non si sa mai) –

+0

Risultati utilizzando Ruby 1.9.3-p327: r1: - "password" r2: - "password" r1: - "1password" r2: - "1password" r1: - "password1" r2: - "password1" r1: - "pass1word" r2: - "pass1word" r1: + "password 1" r2: + "password 1" => ["password", "1 password "," password1 "," pass1word "," password 1 "] Sembra che tu abbia trovato un bug con 1.9.2? –

+0

Puoi includere questo nella tua domanda per favore (per una corretta formattazione) –

risposta

6

Questo risulta dall'interazione tra un paio di caratteristiche regex e Unicode. \W è tutti i caratteri non parola, che include 212A - "KELVIN SIGN" (PDF link) e 017F - "LATIN SMALL LETTER LONG S" ſ (PDF link). Lo /i aggiunge le versioni minuscole di entrambi, che sono i "normali" e s caratteri (006B - "LATIN SMALL LETTER K" and 0073 "LATIN SMALL LETTER S" (PDF link)).

Quindi è lo s in password che in alcuni casi viene interpretato come carattere non di parole.

Si noti che ciò sembra verificarsi solo quando lo \W si trova in una classe di caratteri (ad esempio [\W]). Inoltre posso solo riprodurlo in irb, all'interno di uno script autonomo sembra funzionare come previsto.

Vedere the Ruby bug about this per ulteriori informazioni.

+1

Buona cattura. Non che sia importante, ma il [problema reale] (https://bugs.ruby-lang.org/issues/4044#note-3) non è 'ß' (che è piegato a' ss'), ma 017F - LATIN SMALL LETTER LONG S 's' (che è piegato in un singolo' s'). – user123444555621

+0

@ Pumbaa80 Grazie, ha più senso, ho aggiornato la risposta. Ho preso 'ß' da [un altro commento sul bug report] (https://bugs.ruby-lang.org/issues/4044#note-9). In questo caso, 'ß' corrisponderebbe anche a causa della doppia-s in' password', ma la corrispondenza effettiva è una sola s, quindi è probabilmente 's'. – matt

+0

Wow, questa è una caratteristica interessante :) Grazie per la spiegazione e il link al bug report. –

Problemi correlati